예제 #1
0
    def __init__(self, name, params, cwd=None, env=None, debug=False):
        self.name = name
        self.service_stopped = Signal("stopped signal for " + convert.string2quote(name))
        self.stdin = Queue("stdin for process " + convert.string2quote(name), silent=True)
        self.stdout = Queue("stdout for process " + convert.string2quote(name), silent=True)
        self.stderr = Queue("stderr for process " + convert.string2quote(name), silent=True)

        try:
            self.debug=debug or DEBUG
            self.service = service = subprocess.Popen(
                params,
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                bufsize=-1,
                cwd=cwd,
                env=env
            )

            self.stopper = Signal()
            self.stopper.on_go(self._kill)
            self.thread_locker = Lock()
            self.children = [
                Thread.run(self.name + " waiter", self._monitor, parent_thread=self),
                Thread.run(self.name + " stdin", self._writer, service.stdin, self.stdin, please_stop=self.stopper, parent_thread=self),
                Thread.run(self.name + " stdout", self._reader, service.stdout, self.stdout, please_stop=self.stopper, parent_thread=self),
                # Thread.run(self.name + " stderr", self._reader, service.stderr, self.stderr, please_stop=self.stopper, parent_thread=self),
            ]
        except Exception, e:
            Log.error("Can not call", e)
예제 #2
0
    def __init__(self, name, params, cwd=None, env=None, debug=False):
        self.name = name
        self.service_stopped = Signal("stopped signal for " +
                                      convert.string2quote(name))
        self.stdin = Queue("stdin for process " + convert.string2quote(name),
                           silent=True)
        self.stdout = Queue("stdout for process " + convert.string2quote(name),
                            silent=True)
        self.stderr = Queue("stderr for process " + convert.string2quote(name),
                            silent=True)

        try:
            self.debug = debug or DEBUG
            self.service = service = subprocess.Popen(params,
                                                      stdin=subprocess.PIPE,
                                                      stdout=subprocess.PIPE,
                                                      stderr=subprocess.PIPE,
                                                      bufsize=-1,
                                                      cwd=cwd,
                                                      env=env)

            self.stopper = Signal()
            self.stopper.on_go(self._kill)
            self.thread_locker = Lock()
            self.children = [
                Thread.run(self.name + " waiter",
                           self._monitor,
                           parent_thread=self),
                Thread.run(self.name + " stdin",
                           self._writer,
                           service.stdin,
                           self.stdin,
                           please_stop=self.stopper,
                           parent_thread=self),
                Thread.run(self.name + " stdout",
                           self._reader,
                           service.stdout,
                           self.stdout,
                           please_stop=self.stopper,
                           parent_thread=self),
                Thread.run(self.name + " stderr",
                           self._reader,
                           service.stderr,
                           self.stderr,
                           please_stop=self.stopper,
                           parent_thread=self),
            ]
        except Exception, e:
            Log.error("Can not call", e)
예제 #3
0
 def _convert(v):
     if v is None:
         return "null"
     if v is True:
         return "true"
     if v is False:
         return "false"
     if isinstance(v, basestring):
         return convert.string2quote(v)
     if isinstance(v, (int, long, float)):
         return unicode(v)
     if isinstance(v, dict):
         return "[" + ", ".join(convert.string2quote(k) + ": " + _convert(vv) for k, vv in v.items()) + "]"
     if isinstance(v, list):
         return "[" + ", ".join(_convert(vv) for vv in v) + "]"
예제 #4
0
 def to_ruby(self):
     if isinstance(self.field, Variable):
         return "!doc["+convert.string2quote(self.field.var)+"].isEmpty()"
     elif isinstance(self.field, Literal):
         return self.field.exists().to_ruby()
     else:
         return self.field.to_ruby() + " != null"
예제 #5
0
def value2query(value):
    if isinstance(value, datetime):
        return convert.datetime2milli(value)
    if isinstance(value, Duration):
        return value.milli

    if Math.is_number(value):
        return value
    return convert.string2quote(value)
예제 #6
0
def value2query(value):
    if isinstance(value, datetime):
        return convert.datetime2milli(value)
    if isinstance(value, Duration):
        return value.milli

    if Math.is_number(value):
        return value
    return convert.string2quote(value)
예제 #7
0
class Json2Redshift(object):
    @use_settings
    def __init__(
            self,
            host,
            user,
            password,
            table,
            meta,  # REDSHIFT COPY COMMAND REQUIRES A BUCKET TO HOLD PARAMETERS
            database=None,
            port=5439,
            settings=None):
        self.settings = settings
        self.db = Redshift(settings)
        INDEX_CACHE[settings.table] = wrap(
            {"name": settings.table})  # HACK TO GET parse_columns TO WORK
        columns = parse_columns(settings.table,
                                settings.mapping.test_result.properties)
        nested = [c.name for c in columns if c.type == "nested"]
        self.columns = wrap([
            c for c in columns if c.type not in ["object"] and not any(
                c.name.startswith(n + ".") for n in nested)
        ])

        try:
            self.db.execute("""
                CREATE TABLE {{table_name}} (
                    "_id" character varying UNIQUE,
                    {{columns}}
                )""", {
                "table_name":
                self.db.quote_column(settings.table),
                "columns":
                SQL(",\n".join(
                    self.db.quote_column(c.name) + " " +
                    self.db.es_type2pg_type(c.type) for c in self.columns))
            },
                            retry=False)
        except Exception, e:
            if "already exists" in e:
                Log.alert("Table {{table}} exists in Redshift",
                          table=settings.table)
            else:
                Log.error("Could not make table", e)

        # MAKE jsonpaths FOR COPY COMMAND
        jsonpaths = {
            "jsonpaths": [
                "$" + "".join("[" + convert.string2quote(p) + "]"
                              for p in split_field(c.name))
                for c in self.columns
            ]
        }
        content = convert.value2json(jsonpaths)
        content = content.replace("\\\"", "'")
        # PUSH TO S3
        s3.Bucket(meta).write(meta.jsonspath, content)
예제 #8
0
def value2MVEL(value):
    """
    FROM PYTHON VALUE TO MVEL EQUIVALENT
    """
    if isinstance(value, datetime):
        return str(convert.datetime2milli(value)) + " /*" + value.format("yyNNNdd HHmmss") + "*/"        # TIME
    if isinstance(value, Duration):
        return str(convert.timedelta2milli(value)) + " /*" + str(value) + "*/"    # DURATION

    if Math.is_number(value):
        return str(value)
    return convert.string2quote(value)
예제 #9
0
def value2MVEL(value):
    """
    FROM PYTHON VALUE TO MVEL EQUIVALENT
    """
    if isinstance(value, datetime):
        return str(convert.datetime2milli(value)) + " /*" + value.format("yyNNNdd HHmmss") + "*/"        # TIME
    if isinstance(value, Duration):
        return str(convert.timedelta2milli(value)) + " /*" + str(value) + "*/"    # DURATION

    if Math.is_number(value):
        return str(value)
    return convert.string2quote(value)
예제 #10
0
def compileString2Term(edge):
    if edge.esscript:
        Log.error("edge script not supported yet")

    value = edge.value
    if isKeyword(value):
        value = strings.expand_template("getDocValue({{path}})", {"path": convert.string2quote(value)})
    else:
        Log.error("not handled")

    def fromTerm(value):
        return edge.domain.getPartByKey(value)

    return Dict(toTerm={"head": "", "body": value}, fromTerm=fromTerm)
예제 #11
0
def compileString2Term(edge):
    if edge.esscript:
        Log.error("edge script not supported yet")

    value = edge.value
    if isKeyword(value):
        value = strings.expand_template("getDocValue({{path}})",
                                        {"path": convert.string2quote(value)})
    else:
        Log.error("not handled")

    def fromTerm(value):
        return edge.domain.getPartByKey(value)

    return Data(toTerm={"head": "", "body": value}, fromTerm=fromTerm)
예제 #12
0
    def Parts2Term(self, domain):
        """
        TERMS ARE ALWAYS ESCAPED SO THEY CAN BE COMPOUNDED WITH PIPE (|)

        CONVERT AN ARRAY OF PARTS{name, esfilter} TO AN MVEL EXPRESSION
        RETURN expression, function PAIR, WHERE
            expression - MVEL EXPRESSION
            function - TAKES RESULT OF expression AND RETURNS PART
        """
        fields = domain.dimension.fields

        term = []
        if len(split_field(self.fromData.name)) == 1 and fields:
            if isinstance(fields, Mapping):
                # CONVERT UNORDERED FIELD DEFS
                jx_fields, es_fields = zip(*[(k, fields[k]) for k in sorted(fields.keys())])
            else:
                jx_fields, es_fields = zip(*[(i, e) for i, e in enumerate(fields)])

            # NO LOOPS BECAUSE QUERY IS SHALLOW
            # DOMAIN IS FROM A DIMENSION, USE IT'S FIELD DEFS TO PULL
            if len(es_fields) == 1:
                def fromTerm(term):
                    return domain.getPartByKey(term)

                return Data(
                    head="",
                    body='getDocValue('+convert.string2quote(domain.dimension.fields[0])+')'
                ), fromTerm
            else:
                def fromTerm(term):
                    terms = [convert.pipe2value(t) for t in convert.pipe2value(term).split("|")]

                    candidate = dict(zip(jx_fields, terms))
                    for p in domain.partitions:
                        for k, t in candidate.items():
                            if p.value[k] != t:
                                break
                        else:
                            return p
                    if domain.type in ["uid", "default"]:
                        part = {"value": candidate}
                        domain.partitions.append(part)
                        return part
                    else:
                        return Null

                for f in es_fields:
                    term.append('Value2Pipe(getDocValue('+convert.string2quote(f)+'))')

                return Data(
                    head="",
                    body='Value2Pipe('+('+"|"+'.join(term))+')'
                ), fromTerm
        else:
            for v in domain.partitions:
                term.append("if (" + _where(v.esfilter, lambda x: self._translate(x)) + ") " + value2MVEL(domain.getKey(v)) + "; else ")
            term.append(value2MVEL(domain.getKey(domain.NULL)))

            func_name = "_temp"+UID()
            return self.register_function("+\"|\"+".join(term))
예제 #13
0
 def to_python(self):
     return "((" + convert.string2quote(self.substring) + " in " + self.var.to_python() + ") if " + self.var.to_python() + "!=None else False)"
예제 #14
0
def quote_table(column):
    if _do_not_quote.match(column):
        return column
    return convert.string2quote(column)
def _quote_column(column):
    return convert.string2quote(column.es_column)
예제 #16
0
 def __json__(self):
     return convert.string2quote(self.code)
예제 #17
0
 def to_python(self):
     return qb_expression_to_python(
         self.field) + ".startswith(" + convert.string2quote(
             self.prefix) + ")"
예제 #18
0
def _quote_column(column):
    return convert.string2quote(column.es_column)
예제 #19
0
def DataClass(name, columns):
    """
    Each column has {"name", "required", "nulls", "default", "type"} properties
    """

    columns = wrap([{
        "name": c,
        "required": True,
        "nulls": False,
        "type": object
    } if isinstance(c, basestring) else c for c in columns])
    slots = columns.name
    required = wrap(
        filter(lambda c: c.required and not c.nulls and not c.default,
               columns)).name
    nulls = wrap(filter(lambda c: c.nulls, columns)).name
    types = {c.name: coalesce(c.type, object) for c in columns}

    code = expand_template(
        """
from __future__ import unicode_literals
from collections import Mapping

meta = None
types_ = {{types}}

class {{name}}(Mapping):
    __slots__ = {{slots}}

    def __init__(self, **kwargs):
        if not kwargs:
            return

        for s in {{slots}}:
            setattr(self, s, kwargs.get(s, kwargs.get('default', Null)))

        missed = {{required}}-set(kwargs.keys())
        if missed:
            Log.error("Expecting properties {"+"{missed}}", missed=missed)

        illegal = set(kwargs.keys())-set({{slots}})
        if illegal:
            Log.error("{"+"{names}} are not a valid properties", names=illegal)

    def __getitem__(self, item):
        return getattr(self, item)

    def __setitem__(self, item, value):
        setattr(self, item, value)
        return self

    def __setattr__(self, item, value):
        if item not in {{slots}}:
            Log.error("{"+"{item|quote}} not valid attribute", item=item)
        #if not isinstance(value, types_[item]):
        #    Log.error("{"+"{item|quote}} not of type "+"{"+"{type}}", item=item, type=types_[item])
        object.__setattr__(self, item, value)

    def __getattr__(self, item):
        Log.error("{"+"{item|quote}} not valid attribute", item=item)

    def __hash__(self):
        return object.__hash__(self)

    def __eq__(self, other):
        if isinstance(other, {{name}}) and dict(self)==dict(other) and self is not other:
            Log.error("expecting to be same object")
        return self is other

    def __dict__(self):
        return {k: getattr(self, k) for k in {{slots}}}

    def items(self):
        return ((k, getattr(self, k)) for k in {{slots}})

    def __copy__(self):
        _set = object.__setattr__
        output = object.__new__({{name}})
        {{assign}}
        return output

    def __iter__(self):
        return {{slots}}.__iter__()

    def __len__(self):
        return {{len_slots}}

    def __str__(self):
        return str({{dict}})

temp = {{name}}
""", {
            "name":
            name,
            "slots":
            "(" + (", ".join(convert.value2quote(s) for s in slots)) + ")",
            "required":
            "{" + (", ".join(convert.value2quote(s) for s in required)) + "}",
            "nulls":
            "{" + (", ".join(convert.value2quote(s) for s in nulls)) + "}",
            "len_slots":
            len(slots),
            "dict":
            "{" +
            (", ".join(convert.value2quote(s) + ": self." + s
                       for s in slots)) + "}",
            "assign":
            "; ".join(
                "_set(output, " + convert.value2quote(s) + ", self." + s + ")"
                for s in slots),
            "types":
            "{" + (",".join(
                convert.string2quote(k) + ": " + v.__name__
                for k, v in types.items())) + "}"
        })

    return _exec(code, name)
예제 #20
0
def DataClass(name, columns, constraint=True):
    """
    Use the DataClass to define a class, but with some extra features:
    1. restrict the datatype of property
    2. restrict if `required`, or if `nulls` are allowed
    3. generic constraints on object properties

    It is expected that this class become a real class (or be removed) in the
    long term because it is expensive to use and should only be good for
    verifying program correctness, not user input.

    :param name: Name of the class we are creating
    :param columns: Each columns[i] has properties {
            "name",     - (required) name of the property
            "required", - False if it must be defined (even if None)
            "nulls",    - True if property can be None, or missing
            "default",  - A default value, if none is provided
            "type"      - a Python datatype
        }
    :param constraint: a JSON query Expression for extra constraints
    :return: The class that has been created
    """

    columns = wrap([{"name": c, "required": True, "nulls": False, "type": object} if isinstance(c, basestring) else c for c in columns])
    slots = columns.name
    required = wrap(filter(lambda c: c.required and not c.nulls and not c.default, columns)).name
    nulls = wrap(filter(lambda c: c.nulls, columns)).name
    defaults = {c.name: coalesce(c.default, None) for c in columns}
    types = {c.name: coalesce(c.type, object) for c in columns}

    code = expand_template(
"""
from __future__ import unicode_literals
from collections import Mapping

meta = None
types_ = {{types}}
defaults_ = {{defaults}}

class {{class_name}}(Mapping):
    __slots__ = {{slots}}


    def _constraint(row, rownum, rows):
        return {{constraint_expr}}

    def __init__(self, **kwargs):
        if not kwargs:
            return

        for s in {{slots}}:
            object.__setattr__(self, s, kwargs.get(s, {{defaults}}.get(s, None)))

        missed = {{required}}-set(kwargs.keys())
        if missed:
            Log.error("Expecting properties {"+"{missed}}", missed=missed)

        illegal = set(kwargs.keys())-set({{slots}})
        if illegal:
            Log.error("{"+"{names}} are not a valid properties", names=illegal)

        if not self._constraint(0, [self]):
            Log.error("constraint not satisfied {"+"{expect}}\\n{"+"{value|indent}}", expect={{constraint}}, value=self)

    def __getitem__(self, item):
        return getattr(self, item)

    def __setitem__(self, item, value):
        setattr(self, item, value)
        return self

    def __setattr__(self, item, value):
        if item not in {{slots}}:
            Log.error("{"+"{item|quote}} not valid attribute", item=item)
        object.__setattr__(self, item, value)
        if not self._constraint(0, [self]):
            Log.error("constraint not satisfied {"+"{expect}}\\n{"+"{value|indent}}", expect={{constraint}}, value=self)

    def __getattr__(self, item):
        Log.error("{"+"{item|quote}} not valid attribute", item=item)

    def __hash__(self):
        return object.__hash__(self)

    def __eq__(self, other):
        if isinstance(other, {{class_name}}) and dict(self)==dict(other) and self is not other:
            Log.error("expecting to be same object")
        return self is other

    def __dict__(self):
        return {k: getattr(self, k) for k in {{slots}}}

    def items(self):
        return ((k, getattr(self, k)) for k in {{slots}})

    def __copy__(self):
        _set = object.__setattr__
        output = object.__new__({{class_name}})
        {{assign}}
        return output

    def __iter__(self):
        return {{slots}}.__iter__()

    def __len__(self):
        return {{len_slots}}

    def __str__(self):
        return str({{dict}})

temp = {{class_name}}
""",
        {
            "class_name": name,
            "slots": "(" + (", ".join(convert.value2quote(s) for s in slots)) + ")",
            "required": "{" + (", ".join(convert.value2quote(s) for s in required)) + "}",
            "nulls": "{" + (", ".join(convert.value2quote(s) for s in nulls)) + "}",
            "defaults": jx_expression({"literal": defaults}).to_python(),
            "len_slots": len(slots),
            "dict": "{" + (", ".join(convert.value2quote(s) + ": self." + s for s in slots)) + "}",
            "assign": "; ".join("_set(output, "+convert.value2quote(s)+", self."+s+")" for s in slots),
            "types": "{" + (",".join(convert.string2quote(k) + ": " + v.__name__ for k, v in types.items())) + "}",
            "constraint_expr": jx_expression(constraint).to_python(),
            "constraint": convert.value2json(constraint)
        }
    )

    return _exec(code, name)
예제 #21
0
def DataClass(name, columns):
    """
    Each column has {"name", "required", "nulls", "default", "type"} properties
    """

    columns = wrap([{"name": c, "required": True, "nulls": False, "type": object} if isinstance(c, basestring) else c for c in columns])
    slots = columns.name
    required = wrap(filter(lambda c: c.required and not c.nulls and not c.default, columns)).name
    nulls = wrap(filter(lambda c: c.nulls, columns)).name
    types = {c.name: coalesce(c.type, object) for c in columns}

    code = expand_template("""
from __future__ import unicode_literals
from collections import Mapping

meta = None
types_ = {{types}}

class {{name}}(Mapping):
    __slots__ = {{slots}}

    def __init__(self, **kwargs):
        if not kwargs:
            return

        for s in {{slots}}:
            setattr(self, s, kwargs.get(s, kwargs.get('default', Null)))

        missed = {{required}}-set(kwargs.keys())
        if missed:
            Log.error("Expecting properties {"+"{missed}}", missed=missed)

        illegal = set(kwargs.keys())-set({{slots}})
        if illegal:
            Log.error("{"+"{names}} are not a valid properties", names=illegal)

    def __getitem__(self, item):
        return getattr(self, item)

    def __setitem__(self, item, value):
        setattr(self, item, value)
        return self

    def __setattr__(self, item, value):
        if item not in {{slots}}:
            Log.error("{"+"{item|quote}} not valid attribute", item=item)
        #if not isinstance(value, types_[item]):
        #    Log.error("{"+"{item|quote}} not of type "+"{"+"{type}}", item=item, type=types_[item])
        object.__setattr__(self, item, value)

    def __getattr__(self, item):
        Log.error("{"+"{item|quote}} not valid attribute", item=item)

    def __hash__(self):
        return object.__hash__(self)

    def __eq__(self, other):
        if isinstance(other, {{name}}) and dict(self)==dict(other) and self is not other:
            Log.error("expecting to be same object")
        return self is other

    def __dict__(self):
        return {k: getattr(self, k) for k in {{slots}}}

    def items(self):
        return ((k, getattr(self, k)) for k in {{slots}})

    def __copy__(self):
        _set = object.__setattr__
        output = object.__new__({{name}})
        {{assign}}
        return output

    def __iter__(self):
        return {{slots}}.__iter__()

    def __len__(self):
        return {{len_slots}}

    def __str__(self):
        return str({{dict}})

temp = {{name}}
""",
        {
            "name": name,
            "slots": "(" + (", ".join(convert.value2quote(s) for s in slots)) + ")",
            "required": "{" + (", ".join(convert.value2quote(s) for s in required)) + "}",
            "nulls": "{" + (", ".join(convert.value2quote(s) for s in nulls)) + "}",
            "len_slots": len(slots),
            "dict": "{" + (", ".join(convert.value2quote(s) + ": self." + s for s in slots)) + "}",
            "assign": "; ".join("_set(output, "+convert.value2quote(s)+", self."+s+")" for s in slots),
            "types": "{" + (",".join(convert.string2quote(k) + ": " + v.__name__ for k, v in types.items())) + "}"
        }
    )

    return _exec(code, name)
예제 #22
0
def quote(value):
    if not _convert:
        _late_import()

    return _convert.string2quote(value)
예제 #23
0
 def __json__(self):
     return convert.string2quote(self.code)
예제 #24
0
 def to_python(self):
     return qb_expression_to_python(self.field)+".startswith("+convert.string2quote(self.prefix)+")"
예제 #25
0
def _where(esFilter, _translate):
    if not esFilter or esFilter is True:
        return "true"

    keys = esFilter.keys()
    if len(keys) != 1:
        Log.error("Expecting only one filter aggregate")

    op = keys[0]
    if op == "and":
        list = esFilter[op]
        if not (list):
            return "true"
        if len(list) == 1:
            return _where(list[0], _translate)
        output = "(" + " && ".join(_where(l, _translate) for l in list) + ")"
        return output
    elif op == "or":
        list = esFilter[op]
        if not list:
            return "false"
        if len(list) == 1:
            return _where(list[0], _translate)
        output = "(" + " || ".join(_where(l, _translate) for l in list) + ")"
        return output
    elif op == "not":
        return "!(" + _where(esFilter[op, _translate]) + ")"
    elif op == "term":
        pair = esFilter[op]
        if len(pair.keys()) == 1:
            return [_translate(k) + "==" + value2MVEL(v) for k, v in pair.items()][0]
        else:
            return "(" + " && ".join(_translate(k) + "==" + value2MVEL(v) for k, v in pair.items()) + ")"
    elif op == "terms":
        output = []
        for variableName, valueList in esFilter[op].items():
            if not valueList:
                Log.error("Expecting something in 'terms' array")
            if len(valueList) == 1:
                output.append(_translate(variableName) + "==" + value2MVEL(valueList[0]))
            else:
                output.append("(" + " || ".join(_translate(variableName) + "==" + value2MVEL(v) for v in valueList) + ")")
        return " && ".join(output)
    elif op == "exists":
        # "exists":{"field":"myField"}
        pair = esFilter[op]
        variableName = pair.field
        return "(" + _translate(variableName) + "!=null)"
    elif op == "missing":
        fieldName = _translate(esFilter[op].field)
        testExistence = coalesce(esFilter[op].existence, True)
        testNull = coalesce(esFilter[op].null_value, True)

        output = []
        if testExistence and not testNull:
            output.append("(" + fieldName.replace(".?", ".") + " == empty)")        # REMOVE THE .? SO WE REFER TO THE FIELD, NOT GET THE VALUE
        if testNull:
            output.append("(" + fieldName + "==null)")
        return " || ".join(output)
    elif op == "range":
        pair = esFilter[op]
        ranges = []

        for variableName, r in pair.items():
            if r.gte:
                ranges.append(value2MVEL(r.gte) + "<=" + _translate(variableName))
            elif r.gt:
                ranges.append(value2MVEL(r.gt) + "<" + _translate(variableName))
            elif r["from"]:
                if r.include_lower == None or r.include_lower:
                    ranges.append(value2MVEL(r["from"]) + "<=" + _translate(variableName))
                else:
                    ranges.append(value2MVEL(r["from"]) + "<" + _translate(variableName))

            if r.lte:
                ranges.append(value2MVEL(r.lte) + ">=" + _translate(variableName))
            elif r.lt:
                ranges.append(value2MVEL(r.lt) + ">" + _translate(variableName))
            elif r["from"]:
                if r.include_lower == None or r.include_lower:
                    ranges.append(value2MVEL(r["from"]) + ">=" + _translate(variableName))
                else:
                    ranges.append(value2MVEL(r["from"]) + ">" + _translate(variableName))

        return "("+" && ".join(ranges)+")"

    elif op == "script":
        script = esFilter[op].script
        return _translate(script)
    elif op == "prefix":
        pair = esFilter[op]
        variableName, value = pair.items()[0]
        return _translate(variableName) + ".startsWith(" + convert.string2quote(value) + ")"
    elif op == "match_all":
        return "true"
    else:
        Log.error("'" + op + "' is an unknown aggregate")

    return ""
예제 #26
0
 def to_ruby(self):
     return qb_expression_to_ruby(
         self.field) + ".start_with? " + convert.string2quote(self.prefix)
예제 #27
0
def qb_expression_to_ruby(expr):
    if expr == None:
        return "nil"
    elif Math.is_number(expr):
        return unicode(expr)
    elif is_keyword(expr):
        return "doc[" + convert.string2quote(expr) + "].value"
    elif isinstance(expr, basestring):
        Log.error("{{name|quote}} is not a valid variable name", name=expr)
    elif isinstance(expr, CODE):
        return expr.code
    elif isinstance(expr, Date):
        return unicode(expr.unix)
    elif expr is True:
        return "true"
    elif expr is False:
        return "false"

    op, term = expr.items()[0]

    mop = ruby_multi_operators.get(op)
    if mop:
        if isinstance(term, list):
            if not term:
                return mop[1]  # RETURN DEFAULT
            else:
                output = mop[0].join(
                    ["(" + qb_expression_to_ruby(t) + ")" for t in term])
                return output
        elif isinstance(term, Mapping):
            a, b = term.items()[0]
            output = "(" + qb_expression_to_ruby(
                a) + ")" + mop[0] + "(" + qb_expression_to_ruby(b) + ")"
            return output
        else:
            qb_expression_to_ruby(term)

    bop = ruby_binary_operators.get(op)
    if bop:
        if isinstance(term, list):
            output = bop.join(
                ["(" + qb_expression_to_ruby(t) + ")" for t in term])
            return output
        elif isinstance(term, Mapping):
            if op == "eq":
                # eq CAN ACCEPT A WHOLE OBJECT OF key:value PAIRS TO COMPARE
                output = " and ".join("(" + qb_expression_to_ruby(a) + ")" +
                                      bop + "(" + qb_expression_to_ruby(b) +
                                      ")" for a, b in term.items())
                return output
            else:
                a, b = term.items()[0]
                output = "(" + qb_expression_to_ruby(
                    a) + ")" + bop + "(" + qb_expression_to_ruby(b) + ")"
                return output
        else:
            Log.error("Expecting binary term")

    uop = ruby_unary_operators.get(op)
    if uop:
        output = expand_template(uop, {"term": qb_expression_to_ruby(term)})
        return output

    cop = complex_operators.get(op)
    if cop:
        output = cop(term).to_ruby()
        return output

    Log.error("`{{op}}` is not a recognized operation", op=op)
예제 #28
0
def quote_table(column):
    return convert.string2quote(column)
예제 #29
0
    def Parts2Term(self, domain):
        """
        TERMS ARE ALWAYS ESCAPED SO THEY CAN BE COMPOUNDED WITH PIPE (|)

        CONVERT AN ARRAY OF PARTS{name, esfilter} TO AN MVEL EXPRESSION
        RETURN expression, function PAIR, WHERE
            expression - MVEL EXPRESSION
            function - TAKES RESULT OF expression AND RETURNS PART
        """
        fields = domain.dimension.fields

        term = []
        if len(split_field(self.fromData.name)) == 1 and fields:
            if isinstance(fields, Mapping):
                # CONVERT UNORDERED FIELD DEFS
                jx_fields, es_fields = zip(*[(k, fields[k])
                                             for k in sorted(fields.keys())])
            else:
                jx_fields, es_fields = zip(*[(i, e)
                                             for i, e in enumerate(fields)])

            # NO LOOPS BECAUSE QUERY IS SHALLOW
            # DOMAIN IS FROM A DIMENSION, USE IT'S FIELD DEFS TO PULL
            if len(es_fields) == 1:

                def fromTerm(term):
                    return domain.getPartByKey(term)

                return Dict(head="",
                            body='getDocValue(' +
                            convert.string2quote(domain.dimension.fields[0]) +
                            ')'), fromTerm
            else:

                def fromTerm(term):
                    terms = [
                        convert.pipe2value(t)
                        for t in convert.pipe2value(term).split("|")
                    ]

                    candidate = dict(zip(jx_fields, terms))
                    for p in domain.partitions:
                        for k, t in candidate.items():
                            if p.value[k] != t:
                                break
                        else:
                            return p
                    if domain.type in ["uid", "default"]:
                        part = {"value": candidate}
                        domain.partitions.append(part)
                        return part
                    else:
                        return Null

                for f in es_fields:
                    term.append('Value2Pipe(getDocValue(' +
                                convert.string2quote(f) + '))')

                return Dict(head="",
                            body='Value2Pipe(' + ('+"|"+'.join(term)) +
                            ')'), fromTerm
        else:
            for v in domain.partitions:
                term.append("if (" +
                            _where(v.esfilter, lambda x: self._translate(x)) +
                            ") " + value2MVEL(domain.getKey(v)) + "; else ")
            term.append(value2MVEL(domain.getKey(domain.NULL)))

            func_name = "_temp" + UID()
            return self.register_function("+\"|\"+".join(term))
예제 #30
0
 def to_ruby(self):
     if self.var == ".":
         return "_source"
     else:
         q = convert.string2quote(self.var)
         return "(doc[" + q + "].isEmpty() ? null : doc[" + q + "].value)"
예제 #31
0
def _where(esFilter, _translate):
    if not esFilter or esFilter is True:
        return "true"

    keys = esFilter.keys()
    if len(keys) != 1:
        Log.error("Expecting only one filter aggregate")

    op = keys[0]
    if op == "and":
        list = esFilter[op]
        if not (list):
            return "true"
        if len(list) == 1:
            return _where(list[0], _translate)
        output = "(" + " && ".join(_where(l, _translate) for l in list) + ")"
        return output
    elif op == "or":
        list = esFilter[op]
        if not list:
            return "false"
        if len(list) == 1:
            return _where(list[0], _translate)
        output = "(" + " || ".join(_where(l, _translate) for l in list) + ")"
        return output
    elif op == "not":
        return "!(" + _where(esFilter[op, _translate]) + ")"
    elif op == "term":
        pair = esFilter[op]
        if len(pair.keys()) == 1:
            return [
                _translate(k) + "==" + value2MVEL(v) for k, v in pair.items()
            ][0]
        else:
            return "(" + " && ".join(
                _translate(k) + "==" + value2MVEL(v)
                for k, v in pair.items()) + ")"
    elif op == "terms":
        output = []
        for variableName, valueList in esFilter[op].items():
            if not valueList:
                Log.error("Expecting something in 'terms' array")
            if len(valueList) == 1:
                output.append(
                    _translate(variableName) + "==" + value2MVEL(valueList[0]))
            else:
                output.append("(" + " || ".join(
                    _translate(variableName) + "==" + value2MVEL(v)
                    for v in valueList) + ")")
        return " && ".join(output)
    elif op == "exists":
        # "exists":{"field":"myField"}
        pair = esFilter[op]
        variableName = pair.field
        return "(" + _translate(variableName) + "!=null)"
    elif op == "missing":
        fieldName = _translate(esFilter[op].field)
        testExistence = coalesce(esFilter[op].existence, True)
        testNull = coalesce(esFilter[op].null_value, True)

        output = []
        if testExistence and not testNull:
            output.append(
                "(" + fieldName.replace(".?", ".") + " == empty)"
            )  # REMOVE THE .? SO WE REFER TO THE FIELD, NOT GET THE VALUE
        if testNull:
            output.append("(" + fieldName + "==null)")
        return " || ".join(output)
    elif op == "range":
        pair = esFilter[op]
        ranges = []

        for variableName, r in pair.items():
            if r.gte:
                ranges.append(
                    value2MVEL(r.gte) + "<=" + _translate(variableName))
            elif r.gt:
                ranges.append(
                    value2MVEL(r.gt) + "<" + _translate(variableName))
            elif r["from"]:
                if r.include_lower == None or r.include_lower:
                    ranges.append(
                        value2MVEL(r["from"]) + "<=" +
                        _translate(variableName))
                else:
                    ranges.append(
                        value2MVEL(r["from"]) + "<" + _translate(variableName))

            if r.lte:
                ranges.append(
                    value2MVEL(r.lte) + ">=" + _translate(variableName))
            elif r.lt:
                ranges.append(
                    value2MVEL(r.lt) + ">" + _translate(variableName))
            elif r["from"]:
                if r.include_lower == None or r.include_lower:
                    ranges.append(
                        value2MVEL(r["from"]) + ">=" +
                        _translate(variableName))
                else:
                    ranges.append(
                        value2MVEL(r["from"]) + ">" + _translate(variableName))

        return "(" + " && ".join(ranges) + ")"

    elif op == "script":
        script = esFilter[op].script
        return _translate(script)
    elif op == "prefix":
        pair = esFilter[op]
        variableName, value = pair.items()[0]
        return _translate(
            variableName) + ".startsWith(" + convert.string2quote(value) + ")"
    elif op == "match_all":
        return "true"
    else:
        Log.error("'" + op + "' is an unknown aggregate")

    return ""
def quote_table(column):
    return convert.string2quote(column)
예제 #33
0
 def to_ruby(self):
     return qb_expression_to_ruby(self.field)+".start_with? "+convert.string2quote(self.prefix)
예제 #34
0
def DataClass(name, columns, constraint=True):
    """
    Use the DataClass to define a class, but with some extra features:
    1. restrict the datatype of property
    2. restrict if `required`, or if `nulls` are allowed
    3. generic constraints on object properties

    It is expected that this class become a real class (or be removed) in the
    long term because it is expensive to use and should only be good for
    verifying program correctness, not user input.

    :param name: Name of the class we are creating
    :param columns: Each columns[i] has properties {
            "name",     - (required) name of the property
            "required", - False if it must be defined (even if None)
            "nulls",    - True if property can be None, or missing
            "default",  - A default value, if none is provided
            "type"      - a Python datatype
        }
    :param constraint: a JSON query Expression for extra constraints
    :return: The class that has been created
    """

    columns = wrap([{
        "name": c,
        "required": True,
        "nulls": False,
        "type": object
    } if isinstance(c, text_type) else c for c in columns])
    slots = columns.name
    required = wrap(
        filter(lambda c: c.required and not c.nulls and not c.default,
               columns)).name
    nulls = wrap(filter(lambda c: c.nulls, columns)).name
    defaults = {c.name: coalesce(c.default, None) for c in columns}
    types = {c.name: coalesce(c.type, object) for c in columns}

    code = expand_template(
        """
from __future__ import unicode_literals
from collections import Mapping

meta = None
types_ = {{types}}
defaults_ = {{defaults}}

class {{class_name}}(Mapping):
    __slots__ = {{slots}}


    def _constraint(row, rownum, rows):
        return {{constraint_expr}}

    def __init__(self, **kwargs):
        if not kwargs:
            return

        for s in {{slots}}:
            object.__setattr__(self, s, kwargs.get(s, {{defaults}}.get(s, None)))

        missed = {{required}}-set(kwargs.keys())
        if missed:
            Log.error("Expecting properties {"+"{missed}}", missed=missed)

        illegal = set(kwargs.keys())-set({{slots}})
        if illegal:
            Log.error("{"+"{names}} are not a valid properties", names=illegal)

        if not self._constraint(0, [self]):
            Log.error("constraint not satisfied {"+"{expect}}\\n{"+"{value|indent}}", expect={{constraint}}, value=self)

    def __getitem__(self, item):
        return getattr(self, item)

    def __setitem__(self, item, value):
        setattr(self, item, value)
        return self

    def __setattr__(self, item, value):
        if item not in {{slots}}:
            Log.error("{"+"{item|quote}} not valid attribute", item=item)
        object.__setattr__(self, item, value)
        if not self._constraint(0, [self]):
            Log.error("constraint not satisfied {"+"{expect}}\\n{"+"{value|indent}}", expect={{constraint}}, value=self)

    def __getattr__(self, item):
        Log.error("{"+"{item|quote}} not valid attribute", item=item)

    def __hash__(self):
        return object.__hash__(self)

    def __eq__(self, other):
        if isinstance(other, {{class_name}}) and dict(self)==dict(other) and self is not other:
            Log.error("expecting to be same object")
        return self is other

    def __dict__(self):
        return {k: getattr(self, k) for k in {{slots}}}

    def items(self):
        return ((k, getattr(self, k)) for k in {{slots}})

    def __copy__(self):
        _set = object.__setattr__
        output = object.__new__({{class_name}})
        {{assign}}
        return output

    def __iter__(self):
        return {{slots}}.__iter__()

    def __len__(self):
        return {{len_slots}}

    def __str__(self):
        return str({{dict}})

""", {
            "class_name":
            name,
            "slots":
            "(" + (", ".join(convert.value2quote(s) for s in slots)) + ")",
            "required":
            "{" + (", ".join(convert.value2quote(s) for s in required)) + "}",
            "nulls":
            "{" + (", ".join(convert.value2quote(s) for s in nulls)) + "}",
            "defaults":
            jx_expression({
                "literal": defaults
            }).to_python(),
            "len_slots":
            len(slots),
            "dict":
            "{" +
            (", ".join(convert.value2quote(s) + ": self." + s
                       for s in slots)) + "}",
            "assign":
            "; ".join(
                "_set(output, " + convert.value2quote(s) + ", self." + s + ")"
                for s in slots),
            "types":
            "{" + (",".join(
                convert.string2quote(k) + ": " + v.__name__
                for k, v in types.items())) + "}",
            "constraint_expr":
            jx_expression(constraint).to_python(),
            "constraint":
            value2json(constraint)
        })

    return _exec(code, name)
예제 #35
0
def qb_expression_to_ruby(expr):
    if expr == None:
        return "nil"
    elif Math.is_number(expr):
        return unicode(expr)
    elif is_keyword(expr):
        return "doc[" + convert.string2quote(expr) + "].value"
    elif isinstance(expr, basestring):
        Log.error("{{name|quote}} is not a valid variable name", name=expr)
    elif isinstance(expr, CODE):
        return expr.code
    elif isinstance(expr, Date):
        return unicode(expr.unix)
    elif expr is True:
        return "true"
    elif expr is False:
        return "false"

    op, term = expr.items()[0]

    mop = ruby_multi_operators.get(op)
    if mop:
        if isinstance(term, list):
            if not term:
                return mop[1]  # RETURN DEFAULT
            else:
                output = mop[0].join(["(" + qb_expression_to_ruby(t) + ")" for t in term])
                return output
        elif isinstance(term, Mapping):
            a, b = term.items()[0]
            output = "(" + qb_expression_to_ruby(a) + ")" + mop[0] + "(" + qb_expression_to_ruby(b) + ")"
            return output
        else:
            qb_expression_to_ruby(term)


    bop = ruby_binary_operators.get(op)
    if bop:
        if isinstance(term, list):
            output = bop.join(["(" + qb_expression_to_ruby(t) + ")" for t in term])
            return output
        elif isinstance(term, Mapping):
            if op == "eq":
                # eq CAN ACCEPT A WHOLE OBJECT OF key:value PAIRS TO COMPARE
                output = " and ".join("(" + qb_expression_to_ruby(a) + ")" + bop + "(" + qb_expression_to_ruby(b) + ")" for a, b in term.items())
                return output
            else:
                a, b = term.items()[0]
                output = "(" + qb_expression_to_ruby(a) + ")" + bop + "(" + qb_expression_to_ruby(b) + ")"
                return output
        else:
            Log.error("Expecting binary term")

    uop = ruby_unary_operators.get(op)
    if uop:
        output = expand_template(uop, {"term": qb_expression_to_ruby(term)})
        return output

    cop = complex_operators.get(op)
    if cop:
        output = cop(term).to_ruby()
        return output

    Log.error("`{{op}}` is not a recognized operation",  op= op)
예제 #36
0
def quote(value):
    if not _convert:
        _late_import()

    return _convert.string2quote(value)