import threading
import re
from itertools import izip, count

from redbeans.formats import Format
from redbeans.creole import Creole
from redbeans.markup import IllegalMarkupException, Parser

from . import config, Element, NoResultFound
from . import custom
from .flavors import FLAVORS, FORMATS

# Sentinal value for nondeterministic dependencies
DISCORDIA = 'discordia'

class WikiException(Exception):
    pass

class NoContentException(WikiException):
    pass

def baz_eval(expr,parser):
    elemlocs = _elemdict(parser)
    if '__' in expr:
        # Protect against hackery
        raise WikiException("The string '__' is not allowed to appear in expressions!")
    else:
        try:
            return eval(expr,{"__builtins__":{},
                              "defined":lambda s:s in elemlocs,
                              "get":lambda s,d=None: elemlocs.get(s,d)},
                        elemlocs)
        except Exception,e:
            raise #WikiException(repr(e))

def arg_eval(val,parser):
    if val.startswith('"'):
        assert val.endswith('"')
        # Dumb hack; we should have format to do format.escape or something
        return parser.subparse(val[1:-1])
    else:
        return parser.subparse('<<%s/>>'%val)

QUOTES = frozenset("'\"")
GROUPING = {'(':')'}

def parse_macro_args(argstr):
    escaping = False
    build = ""
    name = 1
    nextname = 1
    nomore = False
    nest = []
    quote = None
    for char in argstr:
        if len(nest) == 0 and quote is None and char.isspace():
            if build:
                yield (name,build)
                if name == nextname:
                    nextname += 1
                build = ""
                name = nextname
                nomore = False
        else:
            if nomore:
                raise WikiException("Text after close paren in %s arg!"
                                    % name)
            build += char
            if char == '\\' and not escaping:
                escaping = True
            else:
                if (quote is None
                    and char in QUOTES):
                    quote = char
                elif char == quote and not escaping:
                    quote = None
                elif len(nest) > 0 and nest[-1] == char:
                    nest.pop()
                    if len(nest) == 0:
                        build = build[:-1]
                        nomore = True
                elif char in GROUPING:
                    if len(nest) == 0 and isinstance(name,int):
                        if len(build) > 1:
                            name = build[:-1]
                        build = ""
                    nest.append(GROUPING[char])
                escaping = False
    if build:
        yield (name,build)
            

def _list_leaves(e):
    assert e.ename is not None
    eval_state.dependencies.add((e.ename,'__children'))
    # -! make more efficient, possibly move to model
    everyone = e.getDescendants()
    for dude in everyone:
        eval_state.dependencies.add((dude.ename,'__children'))
    return e.getLeaves()

TAGPAIR=re.compile(r'<<(\w+).*>>.*?<</\1>>')
def safesplit_tags(string,pat):
    modstr = string
    m = TAGPAIR.search(modstr)
    while m:
        junk = '*'*len(m.group(0))
        modstr = TAGPAIR.sub(junk,modstr,count=1)
        m = TAGPAIR.search(modstr)
    retlist = []
    next = None
    m = pat.search(modstr)
    while m:
        retlist.append((string[0:m.start(0)],next))
        next = string[m.start(0):m.end(0)]
        string = string[m.end(0):]
        modstr = modstr[m.end(0):]
        m = pat.search(modstr)
    retlist.append((string,next))
    return retlist
def safesplit(string,pat):
    return [p[0] for p in safesplit_tags(string,pat)]

def _get_element(ename):
    if ename in eval_state.eoverrides:
        return eval_state.eoverrides[ename]
    elif ename == config.get_element('me',eval_state.dependencies,
                                   meta=True):
        return eval_state.me
    elif ename == config.get_element('parent',eval_state.dependencies,
                                   meta=True):
        eval_state.dependencies.add((eval_state.me.ename,'__parent'))
        return eval_state.me.supertype
    else:
        eval_state.dependencies.add((ename,'__exists'))
        return Element.get(ename)

def _recurse(ename,pname,parser,toPython=False,
             content=None, argstr=u''):
    e = _get_element(ename)

    if pname == config.get_prop('this',eval_state.dependencies):
        pname = eval_state.this
    assert pname is not None
    eval_state.dependencies.add((e.ename if e else ename,pname))

    if pname == config.get_prop('element_name',eval_state.dependencies):
        return format.escape(e.ename)
    else:
        oldme = eval_state.me
        oldthis = eval_state.this
        oldeover = dict(eval_state.eoverrides)
        oldmover = dict(eval_state.moverrides)
        try:
            eval_state.me = e
            eval_state.this = pname
            # Maybe update leaf
            if ename != config.get_element('parent',eval_state.dependencies,
                                           meta=True):
                eval_state.eoverrides[
                    config.get_element('leaf',eval_state.dependencies,
                                       meta=True)] = e
            # Add macro params
            if content is not None:
                eval_state.moverrides[u'content'] = (lambda *ags:
                                                     parser.subparse(content))
            eval_state.moverrides[u'args'] = argstr
            if argstr:
                for var,arg in parse_macro_args(argstr):
                    eval_state.moverrides[u'arg'+unicode(var)] = arg
            try:
                pv = e[pname]
            except KeyError:
                raise WikiException(
                    "Element ##%s## (called as ##%s## by ##%s##) has no property ##%s##!"
                    % (e.ename,ename,oldme.ename,pname))
    
            if toPython:
                return FLAVORS[pv.prop.flavor].toPython(pv,dialect)
            else:
                return FLAVORS[pv.prop.flavor].evaluate(pv,parser)
        finally:
            eval_state.me = oldme
            eval_state.this = oldthis
            eval_state.eoverrides = oldeover
            eval_state.moverrides = oldmover

class _attrelm(object):
    def __init__(self,ename,parser):
        self.__ename = ename
        self.__parser = parser
    def __hasattr__(self,a):
        if a is None:
            return False
        try:
            self[a]
        except KeyError:
            return False
        else:
            return True
    def __getattr__(self,a):
        if a is None:
            raise KeyError()
        return _recurse(self.__ename,a,parser=self.__parser,toPython=True)

class _elemdict(object):
    def __init__(self,parser):
        self.__parser = parser
    def __contains__(self,key):
        if key is None:
            return False
        if key in eval_state.eoverrides or key in eval_state.moverrides:
            return True
        eval_state.dependencies.add((key,'__exists'))
        try:
            e = Element.get(key)
            return True
        except NoResultFound:
            return False
    def __getitem__(self,key):
        if key not in self:
            raise KeyError("No element '%s' exists!"%key)
        if key in eval_state.moverrides:
            return eval_state.moverrides[key]
        else:
            return _attrelm(key,
                            self.__parser)
    def get(self,key,default=None):
        try:
            return self[key]
        except KeyError:
            return default

# Macro-creating helpers
def environment(name,texname=None,tagname=None,texmode='command'):
    if texname is None:
        texname = name
    def env(parser,argstr,content):
        parser.flush()
        args = parse_macro_args(argstr)
        subclasses = []
        for key,val in args:
            if key == 'subclass':
                subclasses.append(baz_eval(val,parser))
            else:
                raise WikiException("Unknown arg '%s' in %s environment!"
                                % (key,name))
        if isinstance(parser.get_format(),FORMATS['html']):
            if tagname is not None:
                return '<%s>%s</%s>\n' % (tagname,parser.subparse(content),
                                          tagname)
            else:
                return '<div class="%s%s">%s</div>\n' % (
                    name,
                    ''.join(' '+c for c in subclasses),
                    parser.fullparse(content))
        elif isinstance(parser.get_format(),FORMATS['tex']):
            if texmode == 'environment':
                return '\\begin{%s}\n%s\n\\end{%s}' % (
                    texname, parser.fullparse(content),texname)
            else:
                return '\\%s{%s}' % (texname,parser.fullparse(content))
        else:
            return parser.fullparse(content)
    return env
def atom(**kw):
    def ato(parser,argstr):
        parser.flush()
        for k in kw:
            if isinstance(parser.get_format(),FORMATS[k]):
                return kw[k]
        else:
            return ""
    return ato
def leafprop(pname):
    def lp(parser,argstr):
        return _recurse(u'leaf',pname,parser)
    return lp
def divided(name,divider,*inner):
    """A macro that turns something like <<card>>Foo<<flip/>>Bar<</card>>
    into
    <div class="card">
    <div class="front">Foo</div>
    <div class="back">Bar</div>
    </div>"""
    divpat = re.compile(r'<<%s\s*/>>'%divider)
    def div(parser,argstr,content):
        parts = safesplit(content,divpat)
        args = parse_macro_args(argstr)
        subclasses = []
        for key,val in args:
            if key == 'subclass':
                subclasses.append(baz_eval(val,parser))
            else:
                raise WikiException("Unknown arg '%s' in %s divided!"
                                % (key,name))
        if len(parts) > len(inner):
            return parser.subparse("Too many ##%s##s in a ##%s##!"%(divider,name))
        else:
            if isinstance(parser.get_format(),FORMATS['html']):
                ret = '<div class="%s%s">\n' % (name,''.join(
                    ' '+c for c in subclasses))
                for i in xrange(len(parts)):
                    ret += '<div class="%s">%s</div>\n' % (inner[i],
                                                           parser.subparse(parts[i]))
                ret += '</div>\n'
                return ret
            elif isinstance(parser.get_format(),FORMATS['tex']):
                ret = '\\begin{%s}\n' % (name)
                for i in xrange(len(parts)):
                    ret += ('\\%s{%s}\n'
                            % (inner[i],
                               parser.subparse(parts[i])))
                ret += '\\end{%s}\n' % (name)
                return ret
            else:
                ret = ""
                for p in parts:
                    ret += parser.subparse(p) + '\n'
                return ret
    return div
            
def illegal(name,*container):
    def ill(parser,argstr):
        return parser.subparse('##%s## may only be used in a %s!'
                        % (name, ' or '.join('##%s##' % c for c in container)))
    return ill

# Helpers used by our macros
class noescape(object):
    """Wrap a format such that it's escape method is a nop."""
    def __init__(self,format):
        self.__format = format
    def escape(self,text):
        return text
    def __getattr__(self,attr):
        return getattr(self.__format,attr)

class maxwe(object):
    def __cmp__(self,other):
        return
MAXWE = maxwe()

def _to_python(ename,pname):
    return _recurse(ename,pname,eval_state.mainparser,format=Format(),
                    toPython=True)

CLOSED_PAT_FORMAT = r'<<%s\s*/>>'
ELSE_PAT = re.compile(r'<<else\s*/>>|<<elif ([^\s/](?:(?:[^/]|/[^>])+[^\s/])?)\s*/>>')
AFTER_PAT = re.compile(r'<<after\s*>>(.+)<</after\s*>>')

class Macros(object):
    @staticmethod
    def nowiki(parser,argstr,content):
        return parser.escape(content)
    @staticmethod
    def par(parser,argstr):
        return parser.subparse('\n\n')
    @staticmethod
    def block(parser,argstr,content):
        return parser.flush()+parser.fullparse(content)
    @staticmethod
    def format(parser,argstr,content):
        if isinstance(parser.get_format(),FORMATS[argstr.strip()]):
            return parser.subparse(content,noescape(format)) # Broken!
        else:
            return ''

    @staticmethod
    def let(parser,argstr,content):
        args = parse_macro_args(argstr)
        oldmover = dict(eval_state.moverrides)
        oldeover = dict(eval_state.eoverrides)
        for k,v in args:
            # TODO: come up with better evaulation logic with the lazy
            #       evaluate magic
            if v.startswith('"'):
                assert v.endswith('"')
                eval_state.moverrides[k] = v[1:-1]
            else:
                eval_state.eoverrides[k] = _get_element(v)
        ret = parser.subparse(content)
        eval_state.eoverrides = oldeover
        eval_state.moverrides = oldmover
        return ret
        
    @staticmethod
    def content(parser,argstr):
        raise NoContentException()

    @staticmethod
    def if_(parser,argstr,content):
        parttags = safesplit_tags(content,ELSE_PAT)
        cond = argstr
        while True:
            val = baz_eval(cond,parser)
            if val:
                break
            else:
                parttags = parttags[1:]
            if len(parttags) <= 0:
                return ''
            tg = parttags[0][1]
            if 'elif' not in tg:
                break
            else:
                cond = ELSE_PAT.match(tg).group(1)
        return parser.subparse(parttags[0][0])
    # You don't need to put staticmethod() when you add things to this at runtime...
    else_ = staticmethod(illegal('else','if'))
    elif_ = staticmethod(illegal('elif','if'))

    @staticmethod
    def expand(parser,argstr,content):
        rescont = ''
        while True:
            m = AFTER_PAT.search(content)
            if m is None:
                break
            rescont += content[:m.start()]
            rescont += parser.subparse(m.group(1))
            content = content[m.end():]
        rescont += content
        return parser.subparse(rescont)

    @staticmethod
    def foreach(parser,argstr,content):
        args = list(parse_macro_args(argstr))
        if len(args) < 2:
            return parser.subparse("**//{{{foreach}}} takes at least two parameters; args parsed as %s!  See [[edit:Macros]]!//**"%args)
        typ = args[0][1]
        nam = args[1][1]
        restr = set()
        orderBy = []
        groupBy = None
        asTree = False
        recursive = False
        ifNone = None
        args = args[2:]
        while len(args) > 0:
            key,arg = args.pop(0)
            if not isinstance(key,int):
                if key.lower() == 'orderby':
                    orderBy +=arg.strip().split()
                elif key.lower() == 'groupby':
                    if ',' in arg:
                        var,groupMarkup = arg.split(',',1)
                    else:
                        var = arg
                        groupMarkup = ''
                    var = var.strip()
                    if ' ' in var:
                        var = var.split()
                        groupBy = var[0]
                        groupName = var[1]
                    else:
                        groupBy = groupName = var
                elif key.lower() == 'ifnone':
                    ifNone = arg
                else:
                    return parser.subparse("**//Unknown {{{foreach}}} parameter '{{{%s}}}'!//**" % key)
            elif arg.lower() == 'astree':
                asTree = True
            elif arg.lower() == 'recursive':
                recursive = True
            else:
                restr.add(arg)
                
        if '.' in typ:
            typ,stuffprop = typ.split('.',1)
        else:
            stuffprop = None
        try:
            elm = _get_element(typ)
        except NoResultFound:
            return parser.subparse('**//No such element {{{%s}}} in foreach!//**' % typ)
            
        if not asTree:
            if not stuffprop:
                # Now do a traversal:
                lst = _list_leaves(elm)
            else:
                assert typ is not None
                eval_state.dependencies.add((typ,stuffprop))
                if stuffprop not in elm:
                    raise WikiException('Element {{{%s}}} has no property {{{%s}}} in foreach!'%(typ,stuffprop))
                try:
                    lst = extractRefs(elm[stuffprop],parser)
                except NoResultFound,e:
                    raise WikiException('%s not defined when expanding %s.%s in foreach!'%(e.message,elm.ename,stuffprop))
                if recursive:
                    new = [([elm],lst)]
                    while len(new) > 0:
                        newnew = []
                        for path,l in new:
                            for n in l:
                                if n in path:
                                    raise WikiException('Infinite %s loop in foreach: %s!'%(stuffprop,'->'.join(path+[n])))
                                eval_state.dependencies.add((n.ename,
                                                             stuffprop))
                                if stuffprop in n:
                                    refs = extractRefs(n[stuffprop],
                                                       parser)
                                    lst += refs
                                    newnew.append((path+[n],refs))
                        new = newnew

            old_overrides = dict(eval_state.eoverrides)

            if len(restr) > 0:
                filtlst = []
                for e in lst:
                    eval_state.eoverrides[nam] = e
                    if all(baz_eval(r,parser) for r in restr):
                        filtlst.append(e)
                lst = filtlst
            if len(lst) == 0 and ifNone is not None:
                return parser.subparse('\n'+ifNone)

            for f in reversed(orderBy):
                lst.sort(key=lambda e:e[f] if f in e else MAXWE)

            ret = ''

            def stickon(e):
                eval_state.eoverrides[nam] = e
                return parser.subparse(content)
            if groupBy:
                groups = {}
                for e in lst:
                    val = e[groupBy] if groupBy in e else MAXWE
                    if val in groups:
                        groups[val].append(e)
                    else:
                        groups[val] = [e]
                old_mover = dict(eval_state.moverrides)
                for g in sorted(groups.keys()):
                    eval_state.moverrides[groupName] = g if g != MAXWE else "???"
                    if groupMarkup:
                        ret += parser.subparse(groupMarkup)
                    for e in groups[g]:
                        ret += stickon(e)
                eval_state.moverrides = old_mover
            else:
                for e in lst:
                    ret += stickon(e)
            eval_state.eoverrides = old_overrides
        else: # asTree
            def dig(e,depth):
                assert e.ename is not None
                eval_state.dependencies.add((e.ename,'__children'))
                old_overrides = dict(eval_state.eoverrides)
                eval_state.eoverrides[nam] = e
                yield parser.subparse('\n '+('*'*depth)+' '+content)
                eval_state.eoverrides = old_overrides

                lst = e.getSubtypes()
                if len(lst) > 0:
                    for f in reversed(orderBy):
                        lst.sort(key=lambda e:e[f] if f in e else MAXWE)
                    for e in lst:
                        for y in dig(e,depth+1):
                            yield y
            ret = ''.join(dig(elm,1))
        return ret

    @staticmethod
    def comment(parser,argstr,content=None):
        return ""

    lheader = staticmethod(environment('lheader',texname='lhead'))
    rheader = staticmethod(environment('rheader',texname='rhead'))
    lfooter = staticmethod(environment('lfooter',texname='lfoot'))
    rfooter = staticmethod(environment('rfooter',texname='rfoot'))

    @staticmethod
    def withheaders(parser,argstr,content): # More descriptive name
        args = parse_macro_args(argstr)
        headfoot = ["","","",""]
        for key,val in args:
            if key in (1,2,3,4):
                headfoot[key-1] = parser.subparse('<<%s/>>'%val)
            else:
                raise WikiException("Unknown arg '%s' in card!"
                                    % (key))
        cont = parser.subparse(content)
        if cont.strip():
            if isinstance(parser.get_format(),FORMATS['html']):
                ret = '''<div class="page">
<div class="lheader">%s</div>
<div class="rheader">%s</div>
<div class="lfooter">%s</div>
<div class="rfooter">%s</div>
''' % tuple(headfoot)
                ret += cont
                ret += '''
</div>
'''
                return ret
            elif isinstance(parser.get_format(),FORMATS['tex']):
                ret = r'''\cleardoublepage
\resetnumbering
\lhead{%s}
\rhead{%s}
\lfoot{%s}
\rfoot{%s}
''' % tuple(headfoot)
                ret += cont
                ret += r'''
\cleardoublepage
'''
                return ret
        else:
            return ""
    
    center = staticmethod(environment('center',tagname='center',
                                      texmode='environment'))
    right = staticmethod(environment('right',
                                      texmode='environment',
                                      texname='flushright'))
    left = staticmethod(environment('left',
                                    texmode='environment',
                                    texname='flushleft'))
    dbox = staticmethod(environment('dbox'))
    clearpage = staticmethod(atom(html=u"<hr />",tex=r'\clearpage'))
    gap = staticmethod(atom(html=u'<div class="gap"></div>',tex=r'\break\vfill'))

    @staticmethod
    def argeval(parser,argstr):
        if ' ' in argstr:
            raise WikiException("##argeval## takes only one parameter!")
        toeval = baz_eval(argstr,parser)
        if toeval.strip():
            return arg_eval(toeval,parser)
        else:
            return ''

def link_func(href,image=False):
    if image and isinstance(eval_state.mainparser.get_format(),
                             FORMATS['tex']):
        assert (':' not in href
                and not href.startswith('/')
                and href.count('/') == 1),href
        eval_state.images.add(href)
        return (href,href,True)
    if ':' not in href and not href.startswith('/'):
        # Normal context-based interpretation
        if eval_state.topthis == config.get_prop(u'product',
                                                  eval_state.dependencies):
            href = 'get:'+href
        else:
            href = 'edit:'+href
    if ':' in href:
        pref,rest = href.split(':',1)
        rest = rest.strip()
        if pref in ('get','edit'):
            if '/' in rest:
                ename,pname = rest.split('/')
            else:
                ename = rest
                pname = None
            if ename in eval_state.eoverrides:
                ename = eval_state.eoverrides[ename].ename
            if pref == 'get':
                uri,text,exists = custom.product_link(ename,
                                                      eval_state.dependencies)
            elif pref == 'edit':
                uri,text,exists = custom.edit_link(ename,
                                                   eval_state.dependencies)
            if pname is not None:
                uri += '/'+pname
            return uri,text,exists
        else:
            # Check interwiki
            iw = Element.get(u'InterwikiConfig')
            if iw is not None and u'prefix' in iw and u'url' in iw:
                for i in _list_leaves(iw):
                    eval_state.dependencies.add((rest,u'prefix'))
                    if unicode(i[u'prefix']) == pref:
                        return unicode(i[u'url'])+rest,href,True
    # None matched
    return href,href,True

def _error(message,parser):
    #raise Exception(message)
    return parser.subparse('//**'+message+'**//')

MACRO_NAME_PAT = re.compile('^([^\s#]+)(?:\#\S+)?')

def macro_func(parser,name,argstr=u'',content=None):
    #print "<<%s %s>>; me=%s, this=%s, eover=%s"% (name,argstr,
    #                                              eval_state.me.ename,
    #                                              eval_state.this,
    #                                              eval_state.eoverrides,
    #                                              )
    # Allow macros to have #foo suffix, to allow nesting
    m=MACRO_NAME_PAT.match(name)
    assert m is not None
    name = m.group(1)
    argstr = argstr.strip() if argstr else u''
    if '.' not in name and name not in eval_state.moverrides and not hasattr(macros,name) and not hasattr(macros,name+'_'):
        name += u'.'+config.get_prop(u'substitution',eval_state.dependencies)
        maced=True
    else:
        maced=False
    if '.' in name:
        elm,pnam = name.strip().split('.',1)

        try:
            yield _recurse(elm,pnam,parser,content=content,
                           argstr=argstr)
        except NoResultFound:
            if maced:
                yield _error("No element or macro ##%s## exists!" % elm,
                             parser)
            else:
                yield _error("No element ##%s## exists!" % elm,
                             parser)
        except NoContentException:
            raise
        except WikiException,e:
            yield _error(e.message,parser)
    else:
        if name in eval_state.moverrides:
            ove =  eval_state.moverrides[name]
            if hasattr(ove,'__call__'):
                yield ove(parser,argstr,content)
            else:
                yield ove
            return
        if hasattr(macros,name+'_'):
            name = name+'_'
        if hasattr(macros,name):
            if content is not None:
                yield getattr(macros,name)(parser=parser,
                                           argstr=argstr,content=content)
            else:
                yield getattr(macros,name)(parser=parser,
                                           argstr=argstr)
        elif hasattr(format,name):
            if content is not None:
                for g in getattr(format,name)(content=parser.subparse(content)):
                    yield g
            else:
                for g in getattr(format,name)():
                    yield g

        else:
            yield parser.subparse('**//Error: no such macro %s!//**'%name)

# Set this to change the markup dialect used
dialect = Creole(macro_func,link_func)

# Set or add to this to change what macros are available
macros = Macros()

def extractRefs(propval,parser):
    assert propval.prop.flavor == 'references'
    exs = _recurse(propval.element.ename,propval.prop.name,parser,
                   toPython=True)
    for ename in exs:
        eval_state.dependencies.add((ename,'__exists'))
    ret=[]
    for ename in exs:
        try:
            ret.append(Element.get(ename))
        except NoResultFound:
            pass
    return ret

# This is a bit of a hack; we could allow some state to get passed through
# AbstractMarkup.evaluate...
eval_state = threading.local()

def evaluate(propval,extension,toPython=False):
    assert propval.element is not None, propval.id
    assert propval.element.ename is not None
    assert propval.prop.name is not None

    eval_state.topthis = propval.prop.name
    eval_state.dependencies = set([(propval.element.ename,propval.prop.name)])
    eval_state.me = propval.element
    eval_state.this = propval.prop.name
    eval_state.eoverrides = {
        config.get_element(u'current',eval_state.dependencies,
                           meta=True):propval.element,
        config.get_element(u'leaf',eval_state.dependencies,
                           meta=True): propval.element
        }
    eval_state.moverrides = {u'args':""}
    eval_state.images = set()
    assert propval.value is not None,propval

    if extension in FORMATS:
        fmt = FORMATS[extension]()
        mainparser = Parser(fmt,dialect)
        eval_state.mainparser = mainparser
    else:
        mainparser = extension
    try:
        flav = FLAVORS[propval.prop.flavor]
        if not toPython:
            res = flav.evaluate(propval,mainparser)
        else:
            res = flav.toPython(propval,dialect)
    except NoContentException,e:
        if toPython:
            raise
        res = dialect.evaluate(u"Content unspecified, raw markup: {{{"
                               +unicode(propval.value,'utf-8')+"}}}",
                               fmt)
    except WikiException,e:
        if toPython:
            raise
        #import sys
        #tb = sys.exc_info()[2]
        #while tb.tb_next:
        #    tb = tb.tb_next
        res = dialect.evaluate(u"//**Wiki Error**//: %s"% str(e.args[0])
                               #+" at %s.%s"
                               #%(tb.tb_frame.f_code.co_filename,
                               #tb.tb_lineno),
                               , FORMATS[extension]())
        #del tb
    
    return res,eval_state.dependencies,{'images':eval_state.images}

