def _create_path_nodes(self, path, name, unique): node_names = [] for i, node in enumerate(path.nodes): if isinstance(node, NodePointer): node_names.append(_(node.address)) # Switch out node with object from elsewhere in entity list nodes = list(path.nodes) try: target_node = self.entities[node.address] except IndexError: raise IndexError("Node pointer {%s} out of range" % node.address) if not isinstance(target_node, Node): raise ValueError("Pointer {%s} does not refer to a node" % node.address) nodes[i] = target_node path._Path__nodes = tuple(nodes) elif node in self: node_name = _(self.entities.index(node)) node_names.append(node_name) elif unique and not node.bound: node_name = name + "n" + ustr(i) node_names.append(node_name) self.return_clause.append(node_name) else: node_name = name + "n" + ustr(i) node_names.append(node_name) self._create_node(node, node_name) return node_names
def create_path(self, path, name): node_names = [] for i, node in enumerate(path.nodes): if isinstance(node, NodePointer): node_names.append(_(node.address)) # Switch out node with object from elsewhere in entity list nodes = list(path.nodes) node = self.entities[node.address] if not isinstance(node, Node): raise ValueError("Pointer does not refer to a node") nodes[i] = node path.__nodes = tuple(nodes) else: node_name = name + "n" + ustr(i) node_names.append(node_name) self.create_node(node, node_name) rel_names = [] for i, rel in enumerate(path.rels): rel_name = name + "r" + ustr(i) rel_names.append(rel_name) if rel.bound: self.start_clause.append("{name}=rel({{{name}}})".format(name=rel_name)) self.params[rel_name] = rel._id else: if rel.properties: template = "({start})-[{name}:{type} {{{name}}}]->({end})" self.params[rel_name] = rel.properties else: template = "({start})-[{name}:{type}]->({end})" kwargs = {"start": node_names[i], "name": rel_name, "type": cypher_escape(rel.type), "end": node_names[i + 1]} self.create_clause.append(template.format(**kwargs)) self.return_clause.append(rel_name) return node_names, rel_names
def _node_remove_labels(self, *labels): from py2neo.batch import WriteBatch labels = [ustr(label) for label in set(flatten(labels))] batch = WriteBatch(self.graph) for label in labels: batch.remove_label(self, label) batch.run()
def hydrate(cls, data, batch): graph = getattr(batch, "graph", None) job_id = data["id"] uri = data["from"] status_code = data.get("status") location = data.get("location") if graph is None or batch[job_id].raw_result: body = data.get("body") else: body = None try: body = graph.hydrate(data.get("body")) except GraphError as error: message = "Batch job %s failed with %s\n%s" % ( job_id, error.__class__.__name__, ustr(error)) raise_from(BatchError(message, batch, job_id, status_code, uri, location), error) else: # If Cypher results, reduce to single row or single value if possible if isinstance(body, RecordList): num_rows = len(body) if num_rows == 0: body = None elif num_rows == 1: body = body[0] num_columns = len(body) if num_columns == 1: body = body[0] return cls(batch, job_id, uri, status_code, location, body)
def _create_path(self, path, name, unique): node_names = self._create_path_nodes(path, name, unique) rel_names = [] for i, rel in enumerate(path.rels): rel_name = name + "r" + ustr(i) rel_names.append(rel_name) if rel.bound: self.start_clause.append("{name}=rel({{{name}}})".format(name=rel_name)) self.parameters[rel_name] = rel._id else: if rel.properties: template = "{start}-[{name}:{type} {{{name}}}]->{end}" self.parameters[rel_name] = rel.properties else: template = "{start}-[{name}:{type}]->{end}" start_index, end_index = i, i + 1 if isinstance(rel, Rev): start_index, end_index = end_index, start_index start_node = path.nodes[start_index] end_node = path.nodes[end_index] start = self._node_pattern(start_node, node_names[start_index], full=(unique and not start_node.bound and start_node not in self)) end = self._node_pattern(end_node, node_names[end_index], full=(unique and not end_node.bound and end_node not in self)) kwargs = {"start": start, "name": rel_name, "type": cypher_escape(rel.type), "end": end} if unique: self.create_unique_clause.append(template.format(**kwargs)) else: self.create_clause.append(template.format(**kwargs)) self.return_clause.append(rel_name) return node_names, rel_names
def main(): script, args = sys.argv[0], sys.argv[1:] if len(args) < 2 or len(args) > 3: _help(script) return try: service_root = ServiceRoot(NEO4J_URI) user_name = args[0] password = args[1] user_manager = UserManager.for_user(service_root, user_name, password) if len(args) == 2: # Check password if user_manager.password_change_required: print("Password change required") else: print("Password change not required") else: # Change password password_manager = user_manager.password_manager new_password = args[2] if password_manager.change(new_password): print("Password change succeeded") else: print("Password change failed") sys.exit(2) except Exception as error: sys.stderr.write("%s: %s\n" % (error.__class__.__name__, ustr(error))) sys.exit(1)
def hydrate(cls, data, batch): graph = getattr(batch, "graph", None) job_id = data["id"] uri = data["from"] status_code = data.get("status") location = data.get("location") if graph is None or batch[job_id].raw_result: body = data.get("body") else: body = None try: body = graph.hydrate(data.get("body")) except GraphError as error: message = "Batch job %s failed with %s\n%s" % ( job_id, error.__class__.__name__, ustr(error)) raise_from( BatchError(message, batch, job_id, status_code, uri, location), error) else: # If Cypher results, reduce to single row or single value if possible if isinstance(body, RecordList): num_rows = len(body) if num_rows == 0: body = None elif num_rows == 1: body = body[0] num_columns = len(body) if num_columns == 1: body = body[0] return cls(batch, job_id, uri, status_code, location, body)
def append(self, statement, parameters=None, **kwparameters): """ Add a statement to the current queue of statements to be executed. :arg statement: the statement to append :arg parameters: a dictionary of execution parameters """ self.__assert_unfinished() s = ustr(statement) p = {} def add_parameters(params): if params: for key, value in dict(params).items(): if isinstance(value, (Node, Rel, Relationship)): value = value._id p[key] = value try: add_parameters(statement.parameters) except AttributeError: pass add_parameters(dict(parameters or {}, **kwparameters)) # OrderedDict is used here to avoid statement/parameters ordering bug log.info("append %r %r", s, p) self.statements.append(OrderedDict([ ("statement", s), ("parameters", p), ("resultDataContents", ["REST"]), ]))
def append(self, statement, parameters=None, **kwparameters): """ Add a statement to the current queue of statements to be executed. :arg statement: the statement to append :arg parameters: a dictionary of execution parameters """ self.__assert_unfinished() s = ustr(statement) p = {} def add_parameters(params): if params: for k, v in dict(params).items(): if isinstance(v, (Node, Rel, Relationship)): v = v._id p[k] = v try: add_parameters(statement.parameters) except AttributeError: pass add_parameters(dict(parameters or {}, **kwparameters)) s, p = presubstitute(s, p) # OrderedDict is used here to avoid statement/parameters ordering bug log.info("append %r %r", s, p) self.statements.append( OrderedDict([ ("statement", s), ("parameters", p), ("resultDataContents", ["REST"]), ]))
def _node_set_labels(self, *labels): """ Replace all labels on this node. :param labels: one or more text labels """ labels = [ustr(label) for label in set(flatten(labels))] self.labels.clear() self.labels.add(*labels)
def _create_path(self, path, name, unique): node_names = [] for i, node in enumerate(path.nodes): if isinstance(node, NodePointer): node_names.append(_(node.address)) # Switch out node with object from elsewhere in entity list nodes = list(path.nodes) try: node = self.entities[node.address] except IndexError: raise IndexError("Node pointer out of range") if not isinstance(node, Node): raise ValueError("Pointer does not refer to a node") nodes[i] = node path._Path__nodes = tuple(nodes) else: node_name = name + "n" + ustr(i) node_names.append(node_name) self.create_node(node, node_name) rel_names = [] for i, rel in enumerate(path.rels): rel_name = name + "r" + ustr(i) rel_names.append(rel_name) if rel.bound: self.start_clause.append( "{name}=rel({{{name}}})".format(name=rel_name)) self.parameters[rel_name] = rel._id else: if rel.properties: template = "({start})-[{name}:{type} {{{name}}}]->({end})" self.parameters[rel_name] = rel.properties else: template = "({start})-[{name}:{type}]->({end})" kwargs = { "start": node_names[i], "name": rel_name, "type": cypher_escape(rel.type), "end": node_names[i + 1] } if unique: self.create_unique_clause.append(template.format(**kwargs)) else: self.create_clause.append(template.format(**kwargs)) self.return_clause.append(rel_name) return node_names, rel_names
def __repr__(self): column_widths = list(map(len, self.columns)) for record in self.data: for i, (column, value) in enumerate(record): column_widths[i] = max(column_widths[i], len(ustr(value))) out = [" " + " | ".join( column.ljust(column_widths[i]) for i, column in enumerate(self.columns) ) + " "] out += ["-" + "-+-".join( "-" * column_widths[i] for i, column in enumerate(self.columns) ) + "-"] for record in self.data: out.append(" " + " | ".join(ustr(value).ljust(column_widths[i]) for i, (column, value) in enumerate(record)) + " ") out = "\n".join(out) return out
def _node_add_labels(self, *labels): labels = [ustr(label) for label in set(flatten(labels))] self.labels.update(labels) try: self.labels.push() except GraphError as err: if err.response.status_code == BAD_REQUEST and err.cause.exception == 'ConstraintViolationException': raise ValueError(err.cause.message) else: raise
def write_identifier(self, identifier): """ Write an identifier. """ if not identifier: raise ValueError("Invalid identifier") identifier = ustr(identifier) safe = all(ch in self.safe_chars for ch in identifier) if not safe: self.file.write(json.dumps(identifier)) else: self.file.write(identifier)
def __repr__(self): if self.__repr is None: lines = [[], [], []] for i, column_width in enumerate(self.__producer.column_widths): value = ustr(self.__values[i]) width = max(column_width, len(value)) lines[0].append(" %s " % self.__columns[i].ljust(width)) lines[1].append("-" * (width + 2)) lines[2].append(" %s " % value.ljust(width)) self.__repr = "\n".join("|+|"[i].join(line) for i, line in enumerate(lines)) + "\n" return self.__repr
def __repr__(self): column_widths = list(map(len, self.columns)) for record in self.data: for i, (column, value) in enumerate(record): column_widths[i] = max(column_widths[i], len(ustr(value))) out = [ " " + " | ".join( column.ljust(column_widths[i]) for i, column in enumerate(self.columns)) + " " ] out += [ "-" + "-+-".join("-" * column_widths[i] for i, column in enumerate(self.columns)) + "-" ] for record in self.data: out.append(" " + " | ".join( ustr(value).ljust(column_widths[i]) for i, (column, value) in enumerate(record)) + " ") out = "\n".join(out) return out
def _jsonify(cls, value): if isinstance(value, list): out = "[" + ", ".join(cls._jsonify(i) for i in value) + "]" elif hasattr(value, "uri") and hasattr(value, "_properties"): metadata = { "uri": ustr(value.uri), "properties": value._properties, } try: metadata.update({ "start": ustr(value.start_node.uri), "type": ustr(value.type), "end": ustr(value.end_node.uri), }) except AttributeError: pass out = json.dumps(metadata, ensure_ascii=False) else: out = json.dumps(value, ensure_ascii=False) return out
def create_path(self, name, path): node_names = [None] * len(path.nodes) rel_names = [None] * len(path.rels) for i, node in enumerate(path.nodes): if isinstance(node, NodePointer): node_names[i] = _(node.address) # Switch out node with object from elsewhere in entity list nodes = list(path.nodes) node = self.entities[node.address] if not isinstance(node, Node): raise ValueError("Pointer does not refer to a node") nodes[i] = node path.__nodes = tuple(nodes) else: node_names[i] = name + "n" + ustr(i) self.create_node(node_names[i], node) for i, rel in enumerate(path.rels): rel_names[i] = name + "r" + ustr(i) self.create_rel(rel_names[i], rel, node_names[i], node_names[i + 1]) return node_names, rel_names
def _node_remove_labels(self, *labels): """ Remove one or more labels from this node. :param labels: one or more text labels """ from py2neo.batch import WriteBatch labels = [ustr(label) for label in set(flatten(labels))] batch = WriteBatch(self.graph) for label in labels: batch.remove_label(self, label) batch.run()
def _stringify(cls, value, quoted=False): if value is None: if quoted: return "null" else: return "" elif isinstance(value, list): out = " ".join( cls._stringify(item, quoted=False) for item in value) if quoted: out = json.dumps(out, separators=(',', ':'), ensure_ascii=False) else: if quoted: try: out = json.dumps(value, ensure_ascii=False) except TypeError: out = json.dumps(ustr(value), ensure_ascii=False) else: out = ustr(value) return out
def _stringify(cls, value, quoted=False): if value is None: if quoted: return "null" else: return "" elif isinstance(value, list): out = " ".join( cls._stringify(item, quoted=False) for item in value ) if quoted: out = json.dumps(out, separators=(',', ':'), ensure_ascii=False) else: if quoted: try: out = json.dumps(value, ensure_ascii=False) except TypeError: out = json.dumps(ustr(value), ensure_ascii=False) else: out = ustr(value) return out
def write_identifier(self, identifier): """ Write an identifier. """ if not identifier: raise ValueError("Invalid identifier") identifier = ustr(identifier) safe = identifier[0] in self.safe_first_chars and all(ch in self.safe_chars for ch in identifier[1:]) if not safe: self.file.write("`") self.file.write(identifier.replace("`", "``")) self.file.write("`") else: self.file.write(identifier)
def write_geoff(self, record_set): nodes = set() rels = set() def update_descriptors(value): if isinstance(value, list): for item in value: update_descriptors(item) elif hasattr(value, "__uri__") and hasattr(value, "_properties"): if hasattr(value, "type"): rels.add(value) else: nodes.add(value) for row in record_set: for i in range(len(row)): update_descriptors(row[i]) for node in sorted(nodes, key=lambda x: x._id): self.out.write(ustr(node)) self.out.write("\n") for rel in sorted(rels, key=lambda x: x._id): self.out.write(ustr(rel)) self.out.write("\n")
def write_identifier(self, identifier): """ Write an identifier. """ if not identifier: raise ValueError("Invalid identifier") identifier = ustr(identifier) safe = (identifier[0] in self.safe_first_chars and all(ch in self.safe_chars for ch in identifier[1:])) if not safe: self.file.write("`") self.file.write(identifier.replace("`", "``")) self.file.write("`") else: self.file.write(identifier)
def main(): script, args = sys.argv[0], sys.argv[1:] try: if args: if 2 <= len(args) <= 3: print(get_auth_token(NEO4J_URI, *args)) else: _help(script) else: _help(script) except Exception as error: sys.stderr.write(ustr(error)) sys.stderr.write("\n") sys.exit(1)
def uri_string(self): if isinstance(self.entity, int): uri_string = "{{{0}}}".format(self.entity) elif isinstance(self.entity, NodePointer): uri_string = "{{{0}}}".format(self.entity.address) else: try: uri_string = self.entity.relative_uri.string except AttributeError: uri_string = ustr(self.entity) if self.offsets: if not uri_string.endswith("/"): uri_string += "/" uri_string += "/".join(map(percent_encode, self.offsets)) return uri_string
def main(): script, args = sys.argv[0], sys.argv[1:] try: if args: if len(args) == 3: edition, version, path = args download(edition, version, path) elif len(args) == 2: edition, version = args download(edition, version) else: _help(script) else: _help(script) except Exception as error: sys.stderr.write(ustr(error)) sys.stderr.write("\n") _help(script) sys.exit(1)
def cast_property(value): """ Cast the supplied property value to something supported by Neo4j, raising an error if this is not possible. """ if isinstance(value, (bool, float)): pass elif isinstance(value, integer_types): if minint <= value <= maxint: pass else: raise ValueError("Integer value out of range: %s" % value) elif isinstance(value, string_types): value = ustr(value) elif isinstance(value, (frozenset, list, set, tuple)): # check each item and all same type list_value = [] list_type = None for item in value: item = cast_property(item) if list_type is None: list_type = type(item) if list_type is list: raise ValueError("Lists cannot contain nested collections") elif not isinstance(item, list_type): raise TypeError("List property items must be of similar types") list_value.append(item) value = list_value elif isinstance(value, (datetime, date, time)): value = value.isoformat() elif isinstance(value, Decimal): # We'll lose some precision here but Neo4j can't # handle decimals anyway. value = float(value) elif isinstance(value, complex): value = [value.real, value.imag] else: from py2neo.cypher.lang import CypherParameter if isinstance(value, CypherParameter): pass else: raise TypeError("Invalid property type: %s" % type(value)) return value
def _create_path(self, path, name, unique): node_names = self._create_path_nodes(path, name, unique) rel_names = [] for i, rel in enumerate(path.rels): rel_name = name + "r" + ustr(i) rel_names.append(rel_name) if rel.bound: self.start_or_match_clause.relationship( rel_name, "{" + rel_name + "}") self.parameters[rel_name] = rel._id else: if rel.properties: template = "{start}-[{name}:{type} {{{name}}}]->{end}" self.parameters[rel_name] = rel.properties else: template = "{start}-[{name}:{type}]->{end}" start_index, end_index = i, i + 1 if isinstance(rel, Rev): start_index, end_index = end_index, start_index start_node = path.nodes[start_index] end_node = path.nodes[end_index] start = self._node_pattern(start_node, node_names[start_index], full=(unique and not start_node.bound and start_node not in self)) end = self._node_pattern(end_node, node_names[end_index], full=(unique and not end_node.bound and end_node not in self)) kwargs = { "start": start, "name": rel_name, "type": cypher_escape(rel.type), "end": end } if unique: self.create_unique_clause.append(template.format(**kwargs)) else: self.create_clause.append(template.format(**kwargs)) self.return_clause.append(rel_name) return node_names, rel_names
def uri_string(self): """ The fully resolved URI string for this target. :rtype: string """ if isinstance(self.entity, int): uri_string = "{{{0}}}".format(self.entity) elif isinstance(self.entity, NodePointer): uri_string = "{{{0}}}".format(self.entity.address) else: try: uri_string = self.entity.ref except AttributeError: uri_string = ustr(self.entity) if self.segments: if not uri_string.endswith("/"): uri_string += "/" uri_string += "/".join(map(percent_encode, self.segments)) return uri_string
def __repr__(self): column_widths = list(map(len, self.columns)) for row in self.data: for i, value in enumerate(row): column_widths[i] = max(column_widths[i], len(str(value))) out = [" " + " | ".join( column.ljust(column_widths[i]) for i, column in enumerate(self.columns) ) + " "] out += ["-" + "-+-".join( "-" * column_widths[i] for i, column in enumerate(self.columns) ) + "-"] for row in self.data: out.append(" " + " | ".join(ustr(value).ljust(column_widths[i]) for i, value in enumerate(row)) + " ") out = "\n".join(out) if len(self.data) == 1: out += "\n(1 row)\n" else: out += "\n({0} rows)\n".format(len(self.data)) return out
def presubstitute(statement, parameters): more = True while more: before, opener, key = statement.partition(u"«") if opener: key, closer, after = key.partition(u"»") try: value = parameters.pop(key) except KeyError: raise KeyError("Expected a presubstitution parameter named %r" % key) if is_integer(value): value = ustr(value) elif isinstance(value, tuple) and all(map(is_integer, value)): value = u"%d..%d" % (value[0], value[-1]) elif is_collection(value): value = ":".join(map(cypher_escape, value)) else: value = cypher_escape(value) statement = before + value + after else: more = False return statement, parameters
def presubstitute(statement, parameters): more = True while more: before, opener, key = statement.partition(u"«") if opener: key, closer, after = key.partition(u"»") try: value = parameters.pop(key) except KeyError: raise KeyError( "Expected a presubstitution parameter named %r" % key) if is_integer(value): value = ustr(value) elif isinstance(value, tuple) and all(map(is_integer, value)): value = u"%d..%d" % (value[0], value[-1]) elif is_collection(value): value = ":".join(map(cypher_escape, value)) else: value = cypher_escape(value) statement = before + value + after else: more = False return statement, parameters
def __unicode__(self): return ustr(self.statement)
def write_parameter(self, parameter): """ Write a parameter key in curly brackets. """ self.file.write("{") self.file.write(ustr(parameter.key)) self.file.write("}")
def _node_set_labels(self, *labels): labels = [ustr(label) for label in set(flatten(labels))] self.labels.clear() self.labels.add(*labels)
def main(): script, args = sys.argv[0], sys.argv[1:] try: if args: command, args = args[0], args[1:] if command == "help": _help(script) elif command == "list": _list(*args) else: warehouse = Warehouse() name, args = args[0], args[1:] box = warehouse.box(name) if command == "install": edition, version = args box.install(edition, version) webserver_port = warehouse._ports[name] webserver_https_port = webserver_port + 1 print("Created server instance %r configured on ports %s and %s" % ( name, webserver_port, webserver_https_port)) elif command == "remove" and not args: box.remove() elif command == "remove" and args[0] == "force": box.remove(force=True) elif command == "rename": new_name, = args box.rename(new_name) elif command == "start": ps = box.server.start() print(ps.service_root.uri) elif command == "stop": box.server.stop() elif command == "open": if box.server: box.server.graph.open_browser() else: raise RuntimeError("Server %r is not running" % name) elif command == "drop" and not args: box.server.store.drop() elif command == "drop" and args[0] == "force": box.server.store.drop(force=True) elif command == "load": path, args = args[0], args[1:] if not args: box.server.store.load(path) elif args[0] == "force": box.server.store.load(path, force=True) else: raise ValueError("Bad command or arguments") elif command == "save": path, args = args[0], args[1:] if not args: box.server.store.save(path) elif args[0] == "force": box.server.store.save(path, force=True) else: raise ValueError("Bad command or arguments") else: raise ValueError("Bad command or arguments") else: _help(script) except Exception as error: sys.stderr.write(ustr(error)) sys.stderr.write("\n") sys.exit(1)
def _delete_path(self, path, name): for i, rel in enumerate(path.relationships): self._delete_relationship(rel, name + "r" + ustr(i)) for i, node in enumerate(path.nodes): self._delete_node(node, name + "n" + ustr(i))
def _(*args): return "".join("_" + ustr(arg) for arg in args)
def write_value(self, value): """ Write a value. """ self.file.write(ustr(json.dumps(value, ensure_ascii=False)))
def _geoff_write(self, params): for key, value in params.items(): self._out.write(key) self._out.write("\t") self._out.write(ustr(value)) self._out.write("\n")
def __repr__(self): parts = ["{" + ustr(self.job_id) + "}", ustr(self.status_code)] if self.content is not None: parts.append(repr(self.content)) return " ".join(parts)
def write_node_pointer(self, node_pointer): """ Write a node. """ self.file.write("(*") self.file.write(ustr(node_pointer.address)) self.file.write(")")
else: if isinstance(params, list): count = len(params) self.param_sets.extend(params) elif isinstance(params, dict): count = 1 self.param_sets.append(params) else: count = 0 if count == 1: print("1 parameter set added") else: print("{0} parameter sets added".format(count)) def remove_parameters(self, line): self.param_sets = [] def show_parameters(self, line): print(json.dumps(self.param_sets, sort_keys=True, indent=4)) if __name__ == "__main__": try: Tool().do(sys.argv) sys.exit(0) except Exception as err: sys.stderr.write(ustr(err)) sys.stderr.write("\n") sys.exit(1)
def __init__(self, statement, parameters=None): body = {"query": ustr(statement)} if parameters: body["params"] = dict(parameters) Job.__init__(self, "POST", self.target, body)
def write_literal(self, text): """ Write literal text. """ self.file.write(ustr(text))