From baaf854cfb41a6d76f62934362a4d91c264e7e2e Mon Sep 17 00:00:00 2001 From: LV-426 Date: Mon, 23 Mar 2015 17:03:34 +0200 Subject: neo4j_util: various code relocations --- src/server/neo4j_util.py | 201 +++++++++++++++++++---------------------------- 1 file changed, 81 insertions(+), 120 deletions(-) (limited to 'src') diff --git a/src/server/neo4j_util.py b/src/server/neo4j_util.py index 1b9943b0..b0eabc0a 100644 --- a/src/server/neo4j_util.py +++ b/src/server/neo4j_util.py @@ -3,7 +3,6 @@ """ import json -import logging import six import string import time @@ -13,9 +12,8 @@ import model from six.moves.urllib import request import six.moves.urllib_error as urllib_error from util import debug_log_duration - - -log = logging.getLogger('rhizi') +import re +from neo4j_cypher import Cypher_Parser class Neo4JException(Exception): def __init__(self, error_set): @@ -24,55 +22,6 @@ class Neo4JException(Exception): def __str__(self): return 'neo4j error set: ' + str(self.error_set) -class DB_Query(object): - - def __init__(self, q_str_or_array, param_set={}): - """ - @param q_str_or_array: cypher query to add - if passed as an array ' '.join(q_str_or_array) - is used to convert it to string type - """ - if type(q_str_or_array) is list: - q_str_or_array = ' '.join(q_str_or_array) - - q_str = q_str_or_array - self.statement = q_str - self.param_set = param_set - - def __str__(self): - return 'q: %s, params: %s' % (self.statement, str(self.param_set)) - - __repr__ = __str__ - -class DB_row(object): - def __init__(self, data): - self.data = data - - def __iter__(self): - for column_val in self.data: - yield column_val - - def items(self): - return [x for x in self] - - def __str__(self): - return str(self.items()) - - def __repr__(self): - return repr(self.items()) - -class DB_result_set(object): - def __init__(self, data): - self.data = data - - def __iter__(self): - for db_row_dict in self.data['data']: - # example: dict: {u'row': [{u'title': u'foo'}]} - assert None != db_row_dict['row'] - - yield DB_row(db_row_dict['row']) - - def items(self): - return [x for x in self] class Cypher_String_Formatter(string.Formatter): """ @@ -91,50 +40,33 @@ class Cypher_String_Formatter(string.Formatter): val = "{" + field_name + "}", field_name return val -def cfmt(fmt_str, *args, **kwargs): - return Cypher_String_Formatter().format(fmt_str, *args, **kwargs) +def __type_check_link_or_node_map(x_map): + for k, v in x_map.iteritems(): # do some type sanity checking + assert isinstance(k, six.string_types) + assert isinstance(v, list) -def quote__backtick(label): +def __type_check_filter_attr_map(filter_attr_map): """ - quote label (possibly containing spaces) with backticks + # type sanity check an attribute filter map """ - return '`' + label + '`' + assert isinstance(filter_attr_map, dict) + for k, v in filter_attr_map.items(): + assert isinstance(k, six.string_types) + assert isinstance(v, list) -def post_neo4j(url, data): +def cfmt(fmt_str, *args, **kwargs): + return Cypher_String_Formatter().format(fmt_str, *args, **kwargs) + +def db_query_set_to_REST_form(db_query_set): """ - @return dict object from the neo4j json POST response + Transform DB_Query set to Neo4J's REST API request format + + ref: http://neo4j.com/docs/stable/rest-api.html """ - ret = post(url, data) - ret_data = json.load(ret) - - # [!] do not raise exception if ret_data['errors'] is not empty - - # this allows query-sets to partially succeed - - return ret_data - -def post(url, data): - assert(isinstance(data, dict)) # make sure we're not handed json strings - - post_data_json = json.dumps(data) - - req = request.Request(url) - req.add_header('User-Agent', 'rhizi-server/0.1') - req.add_header('Accept', 'application/json; charset=UTF-8') - req.add_header('Content-Type', 'application/json') - - req.add_header('X-Stream', 'true') # enable neo4j JSON streaming - - try: - ret = request.urlopen(req, post_data_json) - except urllib_error.HTTPError as e: - raise Exception('post request failed: code: {0}, reason: {1}'.format(e.code, e.reason)) - - return ret -def statement_set_to_REST_form(statement_set): - assert isinstance(statement_set, list) + assert isinstance(db_query_set, list) - def _adapt_single_statement_to_REST_form(query, parameters={}): + def _adapt_single_query_to_REST_form(query, parameters={}): """ turn cypher query to neo4j json API format """ @@ -146,15 +78,16 @@ def statement_set_to_REST_form(statement_set): else: assert isinstance(parameters, dict) - return {'statement' : query, 'parameters': parameters} + return {'statement' : query, + 'parameters': parameters} - rest_statement_set = [] - for db_query in statement_set: - rest_statement = _adapt_single_statement_to_REST_form(db_query.statement, + rest_query_set = [] + for db_query in db_query_set: + rest_query = _adapt_single_query_to_REST_form(db_query.str__cypher_query(), db_query.param_set) - rest_statement_set.append(rest_statement) + rest_query_set.append(rest_query) - return {'statements': rest_statement_set} + return {'statements': rest_query_set} def gen_clause_attr_filter_from_filter_attr_map(filter_attr_map, node_label="n"): if not filter_attr_map: @@ -212,11 +145,11 @@ def gen_query_create_from_node_map(node_map, input_to_DB_property_map=lambda _: __type_check_link_or_node_map(node_map) ret = [] - for label, n_set in node_map.items(): + for n_label, n_set in node_map.items(): - assert valid_label(label), 'malformed label: ' + label + validate_label(n_label) - q_arr = ['create (n:%s {node_attr})' % (quote__backtick(label)), + q_arr = ['create (n:%s {node_attr})' % (quote__backtick(n_label)), 'with n', 'order by n.id', 'return {id: n.id, __label_set: labels(n)}' @@ -247,13 +180,13 @@ def gen_query_create_from_link_map(link_map, input_to_DB_property_map=lambda _: ret = [] for l_type, l_set in link_map.items(): - assert valid_label(l_type), 'malformed label: ' + l_type + validate_label(l_type); - q_arr = ['match (src {id: {src}.id}),(dst {id: {dst}.id})', + q_arr = ['match (src {id: {src}.id}), (dst {id: {dst}.id})', 'create (src)-[r:%(__type)s {link_attr}]->(dst)' % {'__type': quote__backtick(l_type)}, 'with r, src, dst', 'order by r.id', - 'return { id: r.id, __src_id: src.id, __dst_id: dst.id, __type: type(r)}', + 'return {id: r.id, __src_id: src.id, __dst_id: dst.id, __type: type(r)}', ] for link in l_set: @@ -278,6 +211,50 @@ def gen_query_create_from_link_map(link_map, input_to_DB_property_map=lambda _: return ret +def generate_random_id__uuid(): + """ + generate a random UUID based string ID + """ + return str(uuid.uuid4()) + +def post_neo4j(url, data): + """ + @return dict object from the neo4j json POST response + """ + ret = post(url, data) + ret_data = json.load(ret) + + # [!] do not raise exception if ret_data['errors'] is not empty - + # this allows query-sets to partially succeed + + return ret_data + +def post(url, data): + assert(isinstance(data, dict)) # make sure we're not handed json strings + + post_data_json = json.dumps(data) + + req = request.Request(url) + req.add_header('User-Agent', 'rhizi-server/0.1') + req.add_header('Accept', 'application/json; charset=UTF-8') + req.add_header('Content-Type', 'application/json') + + req.add_header('X-Stream', 'true') # enable neo4j JSON streaming + + try: + ret = request.urlopen(req, post_data_json) + except urllib_error.HTTPError as e: + raise Exception('post request failed: code: {0}, reason: {1}'.format(e.code, e.reason)) + + return ret + +def quote__backtick(label): + """ + quote label (possibly containing spaces) with backticks + """ + return '`' + label + '`' + + def meta_attr_list_to_meta_attr_map(e_set, meta_attr='__label_set'): """ convert a list of maps each containing a meta_attr key into a @@ -320,22 +297,6 @@ def meta_attr_list_to_meta_attr_map(e_set, meta_attr='__label_set'): return ret -def generate_random_id__uuid(): - """ - generate a random UUID based string ID - """ - return str(uuid.uuid4()) - -def __type_check_link_or_node_map(x_map): - for k, v in x_map.iteritems(): # do some type sanity checking - assert isinstance(k, six.string_types) - assert isinstance(v, list) - -def __type_check_filter_attr_map(filter_attr_map): - """ - # type sanity check an attribute filter map - """ - assert isinstance(filter_attr_map, dict) - for k, v in filter_attr_map.items(): - assert isinstance(k, six.string_types) - assert isinstance(v, list) +def validate_label(label): + assert len(label) > 0 and (label[0].isupper() or label[0] == '_'), 'malformed label: ' + label + pass -- cgit v1.3.1