from __future__ import unicode_literals
from __future__ import print_function

from .context import dataindex
from .context.tools import to_expression
from .compat import implements_to_string, text_type
from .context.missing import is_missing
from .interface import unproxy

from pyparsing import (
    Word,
    WordEnd,
    nums,
    alphas,
    Combine,
    oneOf,
    opAssoc,
    operatorPrecedence,
    QuotedString,
    Literal,
    ParserElement,
    ParseException,
    Forward,
    Group,
    Suppress,
    Optional,
    Regex,
)

from sqlalchemy import and_, or_, func, not_

import operator
import re
import threading


def dbobject(obj):
    return getattr(obj, "__moyadbobject__", lambda: obj)()


@implements_to_string
class DBExpressionError(Exception):
    hide_py_traceback = True
    error_type = "Database expression error"

    def __init__(self, exp, msg=None, col=None):
        self.exp = exp
        self.msg = msg or ""
        self.col = col

    def __str__(self):
        return self.msg

    def __moyaconsole__(self, console):
        indent = ""
        console(indent + self.exp, bold=True, fg="magenta").nl()
        if self.col: