def project(stream, proj): if not isinstance(stream, Stream): raise FlareSyntaxError( "returning dict top-level keys must be streams.") if proj is True: return {'stream': stream(), 'projection': "default"} elif proj is False: return {'stream': stream(), 'projection': {}} else: nd = {} l = [(proj, nd)] while l: old, new = l.pop(0) for key, val in old.items(): if isinstance(val, EventPath): z = val() new[key] = [{'var': z['path'][1:]}] elif isinstance(val, float): new[key] = [{'lit': {'val': val, 'type': 'double'}}] elif isinstance(val, int): new[key] = [{'lit': {'val': val, 'type': 'int'}}] elif isinstance(val, str): new[key] = [{'lit': {'val': val, 'type': 'string'}}] elif isinstance(val, bool): new[key] = [{'lit': {'val': val, 'type': 'bool'}}] elif isinstance(val, dict): new[key] = {} l.append((val, new[key])) else: raise FlareSyntaxError("%s: %s is unsupported." % (key, val.__class__)) return {'stream': stream(), 'projection': nd}
def __init__(self, *q, **kwargs): """Initialize the switch. TODO: Define q and kwargs """ for c in q: if isinstance(c, Cond): if not isinstance(c.path, EventPath): raise FlareSyntaxError('Use V. for paths within event()') else: raise FlareSyntaxError('Use V. for paths within event()') self._query = (tuple(q), ) self._stream = None
def __call__(self): if self.proj is True: return {'stream': self.stream(), 'projection': "default"} elif self.proj is False: return {'stream': self.stream(), 'projection': False} else: nd = {} l = [(self.proj, nd)] while l: old, new = l.pop(0) for key, val in old.items(): if isinstance(val, EventPath): z = val() new[key] = [{'var': z['path']}] elif isinstance(val, ProjMath): new[key] = [val()] elif isinstance(val, float): new[key] = [{'lit': {'val': val, 'type': 'double'}}] elif isinstance(val, int): new[key] = [{'lit': {'val': val, 'type': 'int'}}] elif isinstance(val, str): new[key] = [{'lit': {'val': val, 'type': 'string'}}] elif isinstance(val, bool): new[key] = [{'lit': {'val': val, 'type': 'bool'}}] elif isinstance(val, dict): new[key] = {} l.append((val, new[key])) else: raise FlareSyntaxError("%s: %s is unsupported." % (key, val.__class__)) return {'stream': self.stream(), 'projection': nd}
def __call__(self): """Generate AST code from the switch.""" if len(self._query) <= 1: raise FlareSyntaxError( "Switches must contain at least two `event()`'s") else: cds = [] for s in self._query: if len(s) > 1: cds.append({'type': '&&', 'args': [x() for x in s]}) elif len(s) == 1: cds.append(s[0]()) else: raise FlareSyntaxError( "Switches must have non-empty conditions") return {'type': 'switch', 'conds': cds, 'stream': self._stream()}
def __str__(self): """Generate a string representation of the switch.""" if len(self._query) < 2: raise FlareSyntaxError("Switches must have two conditions") else: d = " -> ".join(" && ".join( [str(x) if PY3 else str(x).decode('utf-8') for x in q]) for q in self._query) # NOQA if self._stream: return "{}:({})".format(str(self._stream), d) else: return "(" + d + ")"
def convert(p): if isinstance(p, float): return {'lit': {'val': p, 'type': 'double'}} elif isinstance(p, int): return {'lit': {'val': p, 'type': 'int'}} elif isinstance(p, EventPath): return {'var': p()['path']} elif isinstance(p, ProjMath): return p() else: raise FlareSyntaxError( "projection math with non-numeric types is unsupported.") return {'stream': self.stream(), 'projection': nd}
def __call__(self): """Generate an Abstract Syntax Tree for a given query""" q, r = None, None for s in self.statements: if isinstance(s, Select): if q is None: q = s() else: raise FlareSyntaxError( "Only one `select` statement may be present in a query" ) elif isinstance(s, Span): if q is None: z = Select() z._query = [s] q = z() else: raise FlareSyntaxError( "Only one `select` statement may be present in a query" ) elif isinstance(s, Returning): if r is None: r = s() else: raise FlareSyntaxError( "Only one `returning` statement may be present in a query" ) else: raise FlareSyntaxError( "Statement must be either `returning` or `select`") if q is None: q = Select()() if r is None: r = {} q.update(r) return q
def __init__(self, path, op, val): """Initialize the condition. Arguments: path -- the path to a specific attribute of a stream op -- the operator to be checked in the condition val -- the value to check the condition against. """ self.path = path self.op = op self.val = val if isinstance(self.val, InPolygon) or isinstance(self.val, InCircle): if op not in ('==', ): raise FlareSyntaxError( "Only `==` operator can be used with regions")
def span(self, *q, **kwargs): """A span of time where a set of conditions is continuously satisfied. Conditions can be defined across one or more streams. Keyword arguments: min -- The minimum valid span duration `delta()`. max -- The maximum valid span duration `delta()`. exactly -- The exact valid span duration `delta()`. within -- The maximum distance in time between the end of the previous span and the start of this span. after -- The minimum distance in time between the end of the previous span and the start of this span. """ for k in kwargs: if k not in ['min', 'max', 'exactly']: raise FlareSyntaxError( 'first span in a select supports only ' '`min`, `max` and `exactly` duration arguments') if self._query: raise FlareSyntaxError("Use .then method") else: self._query.append(Span(*q, **kwargs)) return self
def __init__(self, *streams, **kwargs): self.projs = [] for s in streams: if isinstance(s, Stream): self.projs.append(Proj(s)) elif isinstance(s, tuple): for x in s: if isinstance(x, Stream): self.projs.append(Proj(x)) elif isinstance(x, Proj): self.projs.append(x) elif isinstance(s, Proj): self.projs.append(s) else: raise FlareSyntaxError( "Invalid projection type in `returning`") self.default = kwargs.get('default', True)
def __call__(self): """Generate AST code from the switch.""" if not self._stream: raise FlareSyntaxError("Switch must be bound to stream") cds = [] for s in self._query: if len(s) < 1: expr = {'expr': True} else: expr = s[-1]() for x in s[-2::-1]: expr = {'expr': '&&', 'args': [x(), expr]} cds.append(expr) if len(cds) == 0: cds = [{'expr': True}, {'expr': True}] elif len(cds) == 1: cds.insert(0, {'expr': True}) return {'type': 'switch', 'conds': cds, 'stream': self._stream()}
def then(self, *q, **kwargs): """A span of time following the previous span satisfying new conditions. Conditions can be defined across one or more streams and must also be satisfied continuously. Keyword arguments: min -- The minimum valid span duration `delta()`. max -- The maximum valid span duration `delta()`. exactly -- The exact valid span duration `delta()`. within -- The maximum distance in time between the end of the previous span and the start of this span. after -- The minimum distance in time between the end of the previous span and the start of this span. """ if not self._query: raise FlareSyntaxError("Use .span method to start select") else: if "after" not in kwargs and "within" not in kwargs: kwargs["within"] = delta(seconds=0) self._query.append(Span(*q, **kwargs)) return self
def __init__(self, stream, proj=True): if not isinstance(stream, Stream): raise FlareSyntaxError( "returning dict top-level keys must be streams.") self.stream = stream self.proj = proj