class CompoundTest(LibFcn): name = prefix + "compoundTest" sig = Sig([{ "datum": P.WildRecord("D", {}) }, { "operator": P.String() }, { "comparisons": P.Array(P.WildRecord("T", {})) }, { "test": P.Fcn([P.Wildcard("D"), P.Wildcard("T")], P.Boolean()) }], P.Boolean()) errcodeBase = 32020 def __call__(self, state, scope, pos, paramTypes, datum, operator, comparisons, test): if operator == "and": for comparison in comparisons: if callfcn(state, scope, test, [datum, comparison]) is False: return False return True elif operator == "or": for comparison in comparisons: if callfcn(state, scope, test, [datum, comparison]) is True: return True return False elif operator == "xor": numTrue = 0 for comparison in comparisons: if callfcn(state, scope, test, [datum, comparison]) is True: numTrue += 1 return numTrue % 2 == 1 else: raise PFARuntimeException("unrecognized logical operator", self.errcodeBase + 0, self.name, pos)
class FanoutBoolean(LibFcn): name = prefix + "fanoutBoolean" sig = Sigs([ Sig([{ "x": P.WildEnum("A") }], P.Array(P.Boolean())), Sig([{ "x": P.String() }, { "dictionary": P.Array(P.String()) }, { "outOfRange": P.Boolean() }], P.Array(P.Boolean())), Sig([{ "x": P.Int() }, { "minimum": P.Int() }, { "maximum": P.Int() }, { "outOfRange": P.Boolean() }], P.Array(P.Boolean())) ]) errcodeBase = 17060 def __call__(self, state, scope, pos, paramTypes, x, *args): if len(args) == 0: return fanoutEnum(x, paramTypes[0]["symbols"]) elif len(args) == 2: if len(args[0]) != len(set(args[0])): raise PFARuntimeException("non-distinct values in dictionary", self.errcodeBase + 0, self.name, pos) return fanoutString(x, args[0], args[1]) elif len(args) == 3: return fanoutInt(x, args[0], args[1], args[2])
class Symmetric(LibFcn): name = prefix + "symmetric" sig = Sigs([Sig([{"x": P.Array(P.Array(P.Double()))}, {"tol": P.Double()}], P.Boolean()), Sig([{"x": P.Map(P.Map(P.Double()))}, {"tol": P.Double()}], P.Boolean())]) errcodeBase = 24100 @staticmethod def same(x, y, tol): if math.isinf(x) and math.isinf(y) and ((x > 0.0 and y > 0.0) or (x < 0.0 and y < 0.0)): return True elif math.isnan(x) and math.isnan(y): return True elif not math.isinf(x) and not math.isnan(x) and not math.isinf(y) and not math.isnan(y): return abs(x - y) < tol else: return False def __call__(self, state, scope, pos, paramTypes, x, tol): if isinstance(x, (list, tuple)) and all(isinstance(xi, (list, tuple)) for xi in x): rows = len(x) if rows < 1: raise PFARuntimeException("too few rows/cols", self.errcodeBase + 0, self.name, pos) cols = len(x[0]) if cols < 1: raise PFARuntimeException("too few rows/cols", self.errcodeBase + 0, self.name, pos) if raggedArray(x): raise PFARuntimeException("ragged columns", self.errcodeBase + 1, self.name, pos) if rows != cols: raise PFARuntimeException("non-square matrix", self.errcodeBase + 2, self.name, pos) return all(all(self.same(x[i][j], x[j][i], tol) for j in range(cols)) for i in range(rows)) elif isinstance(x, dict) and all(isinstance(x[i], dict) for i in x.keys()): keys = list(rowKeys(x).union(colKeys(x))) if len(keys) < 1 or all(len(row) == 0 for row in x.values()): raise PFARuntimeException("too few rows/cols", self.errcodeBase + 0, self.name, pos) return all(all(self.same(x.get(i, {}).get(j, 0.0), x.get(j, {}).get(i, 0.0), tol) for j in keys) for i in keys)
class Tester(LibFcn): sig = Sigs([ Sig([{ "x": P.Bytes() }], P.Boolean()), Sig([{ "x": P.String() }], P.Boolean()) ]) codec = None def __call__(self, state, scope, pos, paramTypes, x): if paramTypes[0] == "bytes" or paramTypes[0] == {"type": "bytes"}: try: codecs.decode(x, self.codec, "strict") except UnicodeDecodeError: return False else: return True else: try: codecs.encode(x, self.codec, "strict") except UnicodeEncodeError: return False else: return True
class IsNum(LibFcn): name = prefix + "isnum" sig = Sigs([Sig([{"x": P.Float()}], P.Boolean()), Sig([{"x": P.Double()}], P.Boolean())]) errcodeBase = 21040 def __call__(self, state, scope, pos, paramTypes, x): return not math.isnan(x) and not math.isinf(x)
class KleeneOr(LibFcn): name = "|||" sig = Sig([{ "x": P.Union([P.Boolean(), P.Null()]) }, { "y": P.Union([P.Boolean(), P.Null()]) }], P.Union([P.Boolean(), P.Null()])) errcodeBase = 18230 def genpy(self, paramTypes, args, pos): return """self.f["|||"](state, scope, {0}, {1}, lambda: ({2}), lambda: ({3}))""".format( *([repr(pos), repr(paramTypes)] + args)) def __call__(self, state, scope, pos, paramTypes, x, y): xval = x() if xval is True or xval == {"boolean": True}: return {"boolean": True} yval = y() if yval is True or yval == {"boolean": True}: return {"boolean": True} elif (xval is False or xval == { "boolean": False }) and (yval is False or yval == { "boolean": False }): return {"boolean": False} else: return None
class LogicalXOr(LibFcn): name = "^^" sig = Sig([{"x": P.Boolean()}, {"y": P.Boolean()}], P.Boolean()) errcodeBase = 18200 def __call__(self, state, scope, pos, paramTypes, x, y): return (x or y) and not (x and y)
class ContainsValue(LibFcn): name = prefix + "containsValue" sig = Sigs([ Sig([{ "m": P.Map(P.Wildcard("A")) }, { "value": P.Wildcard("A") }], P.Boolean()), Sig([{ "m": P.Map(P.Wildcard("A")) }, { "fcn": P.Fcn([P.Wildcard("A")], P.Boolean()) }], P.Boolean()) ]) errcodeBase = 26040 def __call__(self, state, scope, pos, paramTypes, m, value): if callable(value): for v in m.values(): if callfcn(state, scope, value, [v]): return True return False else: for v in m.values(): if v == value: return True return False
class BinarySimilarity(BinaryMetric): name = prefix + "binarySimilarity" sig = Sig([{ "x": P.Array(P.Boolean()) }, { "y": P.Array(P.Boolean()) }, { "c00": P.Double() }, { "c01": P.Double() }, { "c10": P.Double() }, { "c11": P.Double() }, { "d00": P.Double() }, { "d01": P.Double() }, { "d10": P.Double() }, { "d11": P.Double() }], P.Double()) errcodeBase = 28110 def __call__(self, state, scope, pos, paramTypes, x, y, c00, c01, c10, c11, d00, d01, d10, d11): length = len(x) if len(y) != length: raise PFARuntimeException("dimensions of vectors do not match", self.errcodeBase + 0, self.name, pos) a00, a01, a10, a11 = self.countPairs(x, y) return div((c11 * a11 + c10 * a10 + c01 * a01 + c00 * a00), (d11 * a11 + d10 * a10 + d01 * a01 + d00 * a00))
class LogicalNot(LibFcn): name = "!" sig = Sig([{"x": P.Boolean()}], P.Boolean()) errcodeBase = 18210 def genpy(self, paramTypes, args, pos): return "(not {0})".format(*args) def __call__(self, state, scope, pos, paramTypes, x): return not x
class LogicalOr(LibFcn): name = "||" sig = Sig([{"x": P.Boolean()}, {"y": P.Boolean()}], P.Boolean()) errcodeBase = 18190 def genpy(self, paramTypes, args, pos): return "({0} or {1})".format(*args) def __call__(self, state, scope, pos, paramTypes, x, y): return x or y
class Contains(LibFcn): name = prefix + "contains" sig = Sigs([Sig([{"haystack": P.String()}, {"pattern": P.String()}], P.Boolean()), Sig([{"haystack": P.Bytes()}, {"pattern": P.Bytes()}], P.Boolean())]) errcodeBase = 35010 def __call__(self, state, scope, pos, paramTypes, haystack, pattern): haystack, pattern, to = convert(haystack, pattern, paramTypes[0]) re = Regexer(haystack, pattern, self.errcodeBase + 0, self.name, pos) out = re.search(0) re.free() return out
class KleeneNot(LibFcn): name = "!!!" sig = Sig([{ "x": P.Union([P.Boolean(), P.Null()]) }], P.Union([P.Boolean(), P.Null()])) errcodeBase = 18240 def __call__(self, state, scope, pos, paramTypes, x): if x is True or x == {"boolean": True}: return {"boolean": False} elif x is False or x == {"boolean": False}: return {"boolean": True} else: return None
class GreaterThan(LibFcn): name = ">" sig = Sig([{"x": P.Wildcard("A")}, {"y": P.Wildcard("A")}], P.Boolean()) errcodeBase = 18120 def __call__(self, state, scope, pos, paramTypes, x, y): return compare(jsonNodeToAvroType(paramTypes[0]), x, y) > 0
class Contains(LibFcn): name = prefix + "contains" sig = Sig([{"haystack": P.String()}, {"needle": P.String()}], P.Boolean()) errcodeBase = 39030 def __call__(self, state, scope, pos, paramTypes, haystack, needle): return needle in haystack
class Tanimoto(BinaryMetric): name = prefix + "tanimoto" sig = Sig([{ "x": P.Array(P.Boolean()) }, { "y": P.Array(P.Boolean()) }], P.Double()) errcodeBase = 28100 def __call__(self, state, scope, pos, paramTypes, x, y): length = len(x) if len(y) != length: raise PFARuntimeException("dimensions of vectors do not match", self.errcodeBase + 0, self.name, pos) a00, a01, a10, a11 = self.countPairs(x, y) return div((a11 + a00), (a11 + 2 * (a10 + a01) + a00))
class EndsWith(LibFcn): name = prefix + "endswith" sig = Sig([{"haystack": P.String()}, {"needle": P.String()}], P.Boolean()) errcodeBase = 39080 def __call__(self, state, scope, pos, paramTypes, haystack, needle): return haystack.endswith(needle)
class TopN(LibFcn): name = prefix + "topN" sig = Sig([{ "x": P.Wildcard("A") }, { "top": P.Array(P.Wildcard("A")) }, { "n": P.Int() }, { "lessThan": P.Fcn([P.Wildcard("A"), P.Wildcard("A")], P.Boolean()) }], P.Array(P.Wildcard("A"))) errcodeBase = 14110 def __call__(self, state, scope, pos, paramTypes, x, top, n, lessThan): if n <= 0: return [] else: index = 0 for best in top: if callfcn(state, scope, lessThan, [best, x]): break index += 1 if index == len(top): out = top + [x] else: above, below = top[:index], top[index:] out = above + [x] + below return out[:n]
class LessOrEqual(LibFcn): name = "<=" sig = Sig([{"x": P.Wildcard("A")}, {"y": P.Wildcard("A")}], P.Boolean()) errcodeBase = 18150 def __call__(self, state, scope, pos, paramTypes, x, y): return compare(jsonNodeToAvroType(paramTypes[0]), x, y) <= 0
class MissingTest(LibFcn): name = prefix + "missingTest" sig = Sig([{ "datum": P.WildRecord("D", {}) }, { "comparison": P.WildRecord( "T", { "field": P.EnumFields("F", "D"), "operator": P.String(), "value": P.Wildcard("V") }) }], P.Union([P.Null(), P.Boolean()])) errcodeBase = 32010 def __call__(self, state, scope, pos, paramTypes, datum, comparison): # newDatumTypeFields = [{"name": x["name"], "type": removeNull(x["type"])} if x["name"] == comparison["field"] else x for x in paramTypes[0]["fields"]] # newParamTypes = [dict(paramTypes[0], fields=newDatumTypeFields)] + paramTypes[1:] # return simpleComparison(newParamTypes, datum, comparison, False, state.parser) out = simpleComparison(paramTypes, datum, comparison, False, state.parser, self.errcodeBase + 1, self.errcodeBase + 0, self.name, pos) if out is True: return {"boolean": True} elif out is False: return {"boolean": False} else: return out
class UpdateHoltWintersPeriodic(LibFcn): name = prefix + "updateHoltWintersPeriodic" sig = Sig([{ "x": P.Double() }, { "alpha": P.Double() }, { "beta": P.Double() }, { "gamma": P.Double() }, { "state": P.WildRecord( "A", { "level": P.Double(), "trend": P.Double(), "cycle": P.Array(P.Double()), "multiplicative": P.Boolean() }) }], P.Wildcard("A")) errcodeBase = 14050 def __call__(self, state, scope, pos, paramTypes, x, alpha, beta, gamma, theState): if alpha < 0.0 or alpha > 1.0: raise PFARuntimeException("alpha out of range", self.errcodeBase + 0, self.name, pos) if beta < 0.0 or beta > 1.0: raise PFARuntimeException("beta out of range", self.errcodeBase + 1, self.name, pos) if gamma < 0.0 or gamma > 1.0: raise PFARuntimeException("gamma out of range", self.errcodeBase + 2, self.name, pos) level_prev = theState["level"] trend_prev = theState["trend"] cycle_unrotated = theState["cycle"] if len(cycle_unrotated) == 0: raise PFARuntimeException("empty cycle", self.errcodeBase + 3, self.name, pos) cycle_rotated = cycle_unrotated[1:] + [cycle_unrotated[0]] cycle_prev = cycle_rotated[0] if theState["multiplicative"]: level = div(alpha * x, cycle_prev) + (1.0 - alpha) * (level_prev + trend_prev) trend = beta * (level - level_prev) + (1.0 - beta) * trend_prev cycle = div(gamma * x, level) + (1.0 - gamma) * cycle_prev else: level = alpha * (x - cycle_prev) + (1.0 - alpha) * (level_prev + trend_prev) trend = beta * (level - level_prev) + (1.0 - beta) * trend_prev cycle = gamma * (x - level) + (1.0 - gamma) * cycle_prev return dict(theState, level=level, trend=trend, cycle=([cycle] + cycle_rotated[1:]))
class Corresponds(LibFcn): name = prefix + "corresponds" sig = Sig([{ "a": P.Map(P.Wildcard("A")) }, { "b": P.Map(P.Wildcard("B")) }, { "fcn": P.Fcn([P.Wildcard("A"), P.Wildcard("B")], P.Boolean()) }], P.Boolean()) errcodeBase = 26390 def __call__(self, state, scope, pos, paramTypes, a, b, fcn): aset = set(a.keys()) bset = set(b.keys()) if aset != bset: return False else: return all(callfcn(state, scope, fcn, [a[k], b[k]]) for k in aset)
class In(LibFcn, ObjKey): name = prefix + "in" sig = Sig([{ "s": P.Map(P.Wildcard("A")) }, { "x": P.Wildcard("A") }], P.Boolean()) errcodeBase = 26220 def __call__(self, state, scope, pos, paramTypes, s, x): return self.toKey(x, jsonNodeToAvroType(paramTypes[0]["values"])) in s
class IsWeekend(LibFcn): name = prefix + "isWeekend" sig = Sig([{"ts": P.Double()}, {"zone": P.String()}], P.Boolean()) errcodeBase = 40160 def __call__(self, state, scope, pos, paramTypes, ts, zone): day = tz( datetime.datetime.fromtimestamp( tscheck(ts, self.errcodeBase + 1, self.name, pos), UTC()), zone, self.errcodeBase + 0, self.name, pos).weekday() return day == 5 or day == 6
class Disjoint(LibFcn): name = prefix + "disjoint" sig = Sig([{ "a": P.Map(P.Wildcard("A")) }, { "b": P.Map(P.Wildcard("A")) }], P.Boolean()) errcodeBase = 26280 def __call__(self, state, scope, pos, paramTypes, a, b): return len(set(a.keys()).intersection(set(b.keys()))) == 0
class Subset(LibFcn): name = prefix + "subset" sig = Sig([{ "little": P.Map(P.Wildcard("A")) }, { "big": P.Map(P.Wildcard("A")) }], P.Boolean()) errcodeBase = 26270 def __call__(self, state, scope, pos, paramTypes, little, big): return all(k in big for k in little.keys())
class TakeWhile(LibFcn): name = prefix + "takeWhile" sig = Sig([{"a": P.Array(P.Wildcard("A"))}, {"fcn": P.Fcn([P.Wildcard("A")], P.Boolean())}], P.Array(P.Wildcard("A"))) errcodeBase = 15710 def __call__(self, state, scope, pos, paramTypes, a, fcn): out = [] for x in a: if callfcn(state, scope, fcn, [x]): out.append(x) else: break return out
class DropWhile(LibFcn): name = prefix + "dropWhile" sig = Sig([{"a": P.Array(P.Wildcard("A"))}, {"fcn": P.Fcn([P.Wildcard("A")], P.Boolean())}], P.Array(P.Wildcard("A"))) errcodeBase = 15720 def __call__(self, state, scope, pos, paramTypes, a, fcn): i = 0 for ai in a: if callfcn(state, scope, fcn, [ai]): i += 1 else: break return a[i:]
class FilterWithKey(LibFcn): name = prefix + "filterWithKey" sig = Sig([{ "m": P.Map(P.Wildcard("A")) }, { "fcn": P.Fcn([P.String(), P.Wildcard("A")], P.Boolean()) }], P.Map(P.Wildcard("A"))) errcodeBase = 26320 def __call__(self, state, scope, pos, paramTypes, m, fcn): return dict( (k, v) for k, v in m.items() if callfcn(state, scope, fcn, [k, v]))
class IsWorkHours(LibFcn): name = prefix + "isWorkHours" sig = Sig([{"ts": P.Double()}, {"zone": P.String()}], P.Boolean()) errcodeBase = 40170 def __call__(self, state, scope, pos, paramTypes, ts, zone): dt = tz( datetime.datetime.fromtimestamp( tscheck(ts, self.errcodeBase + 1, self.name, pos), UTC()), zone, self.errcodeBase + 0, self.name, pos) day = dt.weekday() hour = dt.hour return (day != 5 or day != 6) and (hour >= 9 and hour < 17)