Source code for bento_meta.util.cypher.clauses

"""
bento_meta.util.cypher.clauses

Representations of Cypher statement clauses, statements,
and statement parameters.
"""
from string import Template
from bento_meta.util.cypher.entities import (
    N, R, P, _return, _condition, _pattern
    )
from bento_meta.util.cypher.functions import Func
from pdb import set_trace

[docs]class Clause(object): """Represents a generic Cypher clause.""" template = Template("$slot1") joiner = ", "
[docs] @staticmethod def context(arg): return _return(arg)
def __init__(self, *args, **kwargs): self.args = list(args) self.kwargs = kwargs
[docs] def __str__(self): values = [] for c in [self.context(x) for x in self.args]: if isinstance(c, str): values.append(c) elif isinstance(c, Func): values.append(str(c)) elif isinstance(c, list): values.extend([str(x) for x in c]) else: values.append(str(c)) return self.template.substitute( slot1=self.joiner.join(values) )
[docs]class Match(Clause): """Create a MATCH clause with the arguments.""" template = Template("MATCH $slot1")
[docs] @staticmethod def context(arg): return _pattern(arg)
def __init__(self, *args): super().__init__(*args)
[docs]class Where(Clause): """Create a WHERE clause with the arguments (joining conditions with 'op').""" template = Template("WHERE $slot1") joiner = " {} "
[docs] @staticmethod def context(arg): return _condition(arg)
def __init__(self, *args, op='AND'): super().__init__(*args, op=op) self.op = op
[docs] def __str__(self): values = [] for c in [self.context(x) for x in self.args]: if isinstance(c, str): values.append(c) elif isinstance(c, Func): values.append(str(c)) elif isinstance(c, list): values.extend([str(x) for x in c]) else: values.append(str(c)) return self.template.substitute( slot1=self.joiner.format(self.op).join(values) )
[docs]class With(Clause): """Create a WITH clause with the arguments.""" template = Template("WITH $slot1") def __init__(self, *args): super().__init__(*args)
[docs]class Create(Clause): """Create a CREATE clause with the arguments.""" template = Template("CREATE $slot1")
[docs] @staticmethod def context(arg): return _pattern(arg)
def __init__(self, *args): super().__init__(*args)
[docs]class Merge(Clause): """Create a MERGE clause with the arguments.""" template = Template("MERGE $slot1")
[docs] @staticmethod def context(arg): return _pattern(arg)
def __init__(self, *args): super().__init__(*args)
[docs]class Remove(Clause): """Create a REMOVE clause with the arguments.""" template = Template("REMOVE $slot1") def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs)
[docs] def __str__(self): ent = self.args[0] item = "" sep = "" if "prop" in self.kwargs: item = self.kwargs["prop"] sep = "." elif "label" in self.kwargs: item = self.kwargs["label"] sep = ":" return self.template.substitute( slot1="{}{}{}".format(self.context(ent),sep,item) )
[docs]class Set(Clause): """ Create a SET clause with the arguments. (Only property arguments matter.) """ template = Template("SET $slot1")
[docs] @staticmethod def context(arg): return _condition(arg)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs)
[docs] def __str__(self): values = [] for c in [self.context(x) for x in self.args if isinstance(x, P)]: if isinstance(c, str): values.append(c) elif isinstance(c, Func): values.append(str(c)) elif isinstance(c, list): values.extend([str(x) for x in c]) else: values.append(str(c)) if 'update' in self.kwargs: values = [x.replace("=","+=") for x in values] return self.template.substitute( slot1=self.joiner.join(values) )
[docs]class OnCreateSet(Set): """Create an ON CREATE SET clause for a MERGE with the arguments.""" template = Template("ON CREATE SET $slot1") def __init__(self, *args): super().__init__(*args)
[docs]class OnMatchSet(Set): """Create an ON CREATE SET clause for a MERGE with the arguments.""" template = Template("ON MATCH SET $slot1") def __init__(self, *args): super().__init__(*args)
[docs]class Return(Clause): """Create a RETURN clause with the arguments.""" template = Template("RETURN $slot1") def __init__(self, *args): super().__init__(*args)
[docs]class OptionalMatch(Clause): """Create an OPTIONAL MATCH clause with the arguments.""" template = Template("OPTIONAL MATCH $slot1")
[docs] @staticmethod def context(arg): return _pattern(arg)
def __init__(self, *args): super().__init__(*args)
[docs]class Collect(Clause): """Create a COLLECT clause with the arguments.""" template = Template("COLLECT $slot1") def __init__(self, *args): super().__init__(*args)
[docs]class Unwind(Clause): """Create an UNWIND clause with the arguments.""" template = Template("UNWIND $slot1") def __init__(self, *args): super().__init__(*args)
[docs]class As(Clause): """Create an AS clause with the arguments.""" template = Template("AS $slot1") def __init__(self, *args): super().__init__(*args)
[docs]class Statement(object): """Create a Neo4j statement comprised of clauses (and strings) in order.""" def __init__(self, *args, terminate=False, use_params=False): self.clauses = args self.terminate = terminate self.use_params = use_params self._params = None
[docs] def __str__(self): stash = P.parameterize if self.use_params: P.parameterize = True else: P.parameterize = False ret = " ".join([str(x) for x in self.clauses]) if self.terminate: ret = ret+";" P.parameterize = stash return ret
# def params(self): # if not self._params: # self._params = re.findall("\\$[a-zA-A0-9_]+", str(self)) # return self._params @property def params(self): if self._params is None: self._params = {} for c in self.clauses: for ent in c.args: if isinstance(ent, (N, R)): for p in ent.props.values(): self._params[p.var] = p.value else: if 'nodes' in vars(type(ent)): for n in ent.nodes(): for p in n.props.values(): self._params[p.var] = p.value if 'edges' in vars(type(ent)): for e in ent.edges(): for p in e.props.values(): self._params[p.var] = p.value return self._params