Ejemplo n.º 1
0
 def __init__(self):
     self.middleware = [WikiWare(), SpamFilter(), DateTimeWare()]
     self.globals = default_context.copy()
     self.xail = XAIL()
     self.load_middleware_macros()
Ejemplo n.º 2
0
class HAL(object):
    version = HALversion

    def __init__(self):
        self.middleware = [WikiWare(), SpamFilter(), DateTimeWare()]
        self.globals = default_context.copy()
        self.xail = XAIL()
        self.load_middleware_macros()

    def load_middleware_macros(self):
        for middleware in self.middleware:
            macros = middleware.get_macros()
            if isinstance(macros, dict):
                self.globals.update(macros)

    def feed(self, *args, **kwargs):
        return self.xail.feed(*args, **kwargs)

    remacro = re.compile(r'{([^{}]+)}')
    refunc  = re.compile(r'(.*?)\((.*?)\)')
    
    def _subst(self, input, context=None):
        if context is None:
            context = {}
        remacro = self.remacro
        refunc = self.refunc
        
        def get(key):
            try:
                return context[key]
            except KeyError:
                return self.globals[key]
        
        while True:
            m = remacro.search(input)
            if m is None:
                break
            action = m.group(1)
            saveto = None
            if action.count('=') > 1:
                raise ValueError('Too many equal signs')
            if '=' in action:
                saveto, action = action.split('=')
            if '(' in action:
                try:
                    name, arg = refunc.match(action).groups()
                except AttributeError:
                    raise ValueError('Invalid function call syntax')
                args = [x.strip() for x in arg.split(',')]
                try:
                    func = get(name)
                except KeyError:
                    raise ValueError('Function not found')
                try:
                    out = func(*args)
                except Exception as e:
                    raise ValueError('Function {0} returned: {1}'.format(name, e))
            else:
                try:
                    data = get(action)
                except KeyError:
                    raise ValueError('Key "{0}" not found'.format(action))
                out = str(data()) if callable(data) else str(data)
            if saveto is None:
                input = '%s%s%s' % (input[:m.start()], out, input[m.end():])
            else:
                context[saveto] = out
                input = input[:m.start()] + input[m.end():]
        return input
    
    def answer(self, question, context=None, recurse=0):
        if recurse > 3:
            return 'Recursion Error'
        
        for middleware in self.middleware:
            response = middleware.input(question)
            if response:
                return response
            response = middleware.filter(question)
            if response:  # Sanity checks here
                question = response

        response = self.xail.final(question)
        
        try:
            response = self._subst(response, context=context)
        except ValueError as e:
            logger.error('Fail to substitute: %s in string %s', e, response)

        for middleware in reversed(self.middleware):
            result = middleware.output(response)
            if result:  # Prevent a bad middleware from eating everything
                response = result
        
        if response.startswith('>'):
            # Only exists for compatibility with old files
            # Will be removed when the main db is cleaned up
            return self.answer(response[1:], context, recurse+1)
        return response