예제 #1
0
 def post(self, resource):
     self.__assert_unfinished()
     rs = resource.post({"statements": self.statements})
     location = rs.location
     if location:
         self.__execute = Resource(location)
     j = rs.content
     rs.close()
     self.statements = []
     if "commit" in j:
         self.__commit = Resource(j["commit"])
     if "errors" in j:
         errors = j["errors"]
         if len(errors) >= 1:
             error = errors[0]
             raise self.error_class.hydrate(error)
     out = RecordListList()
     for result in j["results"]:
         columns = result["columns"]
         producer = RecordProducer(columns)
         out.append(
             RecordList(columns, [
                 producer.produce(self.graph.hydrate(r["rest"]))
                 for r in result["data"]
             ]))
     return out
예제 #2
0
def test_can_handle_json_error_from_post():
    new_node_resource = Resource("http://localhost:7474/db/data/node")
    try:
        new_node_resource.post(["foo"])
    except GraphError:
        assert True
    else:
        assert False
예제 #3
0
def test_can_handle_json_error_from_get():
    resource = Resource("http://localhost:7474/db/data/node/spam")
    try:
        resource.get()
    except ClientError:
        assert True
    else:
        assert False
예제 #4
0
 def __init__(self, uri):
     log.info("begin")
     self.statements = []
     self.__begin = Resource(uri)
     self.__begin_commit = Resource(uri + "/commit")
     self.__execute = None
     self.__commit = None
     self.__finished = False
     self.graph = self.__begin.graph
예제 #5
0
def test_can_handle_json_error_from_delete(graph):
    node, = graph.create({})
    non_existent_property = Resource(node.properties.resource.uri.string + "/foo")
    try:
        non_existent_property.delete()
    except GraphError:
        assert True
    else:
        assert False
예제 #6
0
def test_can_handle_other_error_from_put():
    with patch.object(_Resource, "put") as mocked:
        mocked.side_effect = DodgyServerError
        resource = Resource("http://localhost:7474/db/data/node/spam")
        try:
            resource.put()
        except GraphError as error:
            assert isinstance(error.__cause__, DodgyServerError)
        else:
            assert False
예제 #7
0
def test_can_handle_other_error_from_put():
    with patch.object(_Resource, "put") as mocked:
        mocked.side_effect = DodgyServerError
        resource = Resource("http://localhost:7474/db/data/node/spam")
        try:
            resource.put()
        except GraphError as error:
            assert isinstance(error.__cause__, DodgyServerError)
        else:
            assert False
예제 #8
0
def test_can_handle_400():
    resource = Resource("http://localhost:7474/db/data/cypher")
    try:
        resource.post()
    except GraphError as error:
        assert_error(
            error, (GraphError,), "org.neo4j.server.rest.repr.BadInputException",
            (_ClientError, _Response), 400)
    else:
        assert False
예제 #9
0
def test_can_handle_other_error_from_post():
    with patch.object(_Resource, "post") as mocked:
        mocked.side_effect = DodgyServerError
        resource = Resource("http://localhost:7474/db/data/node/spam")
        try:
            resource.post()
        except DodgyServerError:
            assert True
        else:
            assert False
예제 #10
0
def test_can_handle_json_error_from_post():
    new_node_resource = Resource("http://localhost:7474/db/data/node")
    try:
        new_node_resource.post(["foo"])
    except GraphError as error:
        cause = error.__cause__
        assert isinstance(cause, _ClientError)
        assert isinstance(cause, _Response)
        assert cause.status_code == 400
    else:
        assert False
예제 #11
0
def test_can_handle_json_error_from_get():
    resource = Resource("http://localhost:7474/db/data/node/spam")
    try:
        resource.get()
    except GraphError as error:
        cause = error.__cause__
        assert isinstance(cause, _ClientError)
        assert isinstance(cause, _Response)
        assert cause.status_code == 404
    else:
        assert False
예제 #12
0
def test_can_handle_409(graph):
    node_id = get_attached_node_id(graph)
    resource = Resource("http://localhost:7474/db/data/node/%s" % node_id)
    try:
        resource.delete()
    except GraphError as error:
        assert_error(
            error, (GraphError,), "org.neo4j.server.rest.web.OperationFailureException",
            (_ClientError, _Response), 409)
    else:
        assert False
예제 #13
0
def test_can_handle_404(graph):
    node_id = get_non_existent_node_id(graph)
    resource = Resource("http://localhost:7474/db/data/node/%s" % node_id)
    try:
        resource.get()
    except GraphError as error:
        assert_error(
            error, (GraphError,), "org.neo4j.server.rest.web.NodeNotFoundException",
            (_ClientError, _Response), 404)
    else:
        assert False
예제 #14
0
def test_can_handle_json_error_from_get():
    resource = Resource("http://localhost:7474/db/data/node/spam")
    try:
        resource.get()
    except GraphError as error:
        cause = error.__cause__
        assert isinstance(cause, _ClientError)
        assert isinstance(cause, _Response)
        assert cause.status_code == 404
    else:
        assert False
예제 #15
0
def test_can_handle_json_error_from_post():
    new_node_resource = Resource("http://localhost:7474/db/data/node")
    try:
        new_node_resource.post(["foo"])
    except GraphError as error:
        cause = error.__cause__
        assert isinstance(cause, _ClientError)
        assert isinstance(cause, _Response)
        assert cause.status_code == 400
    else:
        assert False
예제 #16
0
def test_can_handle_json_error_from_delete(graph):
    node, = graph.create({})
    non_existent_property = Resource(node.properties.resource.uri.string + "/foo")
    try:
        non_existent_property.delete()
    except GraphError as error:
        cause = error.__cause__
        assert isinstance(cause, _ClientError)
        assert isinstance(cause, _Response)
        assert cause.status_code == 404
    else:
        assert False
예제 #17
0
def test_can_handle_json_error_from_delete(graph):
    node, = graph.create({})
    non_existent_property = Resource(node.properties.resource.uri.string +
                                     "/foo")
    try:
        non_existent_property.delete()
    except GraphError as error:
        cause = error.__cause__
        assert isinstance(cause, _ClientError)
        assert isinstance(cause, _Response)
        assert cause.status_code == 404
    else:
        assert False
예제 #18
0
파일: neo4j.py 프로젝트: svacha/cycli
    def constraints(self):
        if not self.__constraints:
            constraints = []
            constraints_resource = Resource(self.graph.uri.string + "schema/constraint")
            constraints_content = list(constraints_resource.get().content)

            for i in constraints_content:
                constraint = dict(i)
                constraint["property_keys"] = list(constraint["property_keys"])
                constraints.append(constraint)

            self.__constraints = constraints

        return self.__constraints
예제 #19
0
파일: neo4j.py 프로젝트: svacha/cycli
    def indexes(self):
        if not self.__indexes:
            indexes = []
            for label in self.labels():
                index_resource = Resource(self.graph.uri.string + "schema/index/" + label)
                indexes_content = list(index_resource.get().content)

                for i in indexes_content:
                    index = dict(i)
                    index["property_keys"] = list(index["property_keys"])
                    indexes.append(index)

            self.__indexes = indexes

        return self.__indexes
예제 #20
0
 def test_can_init_server_plugin(self):
     remote_graph = remote(self.graph)
     metadata = remote_graph.metadata
     metadata["extensions"]["FakePlugin"] = {}
     self.graph.__remote__ = Resource(remote_graph.uri, metadata)
     plugin = FakePlugin(self.graph)
     assert plugin.resources == {}
예제 #21
0
 def __init__(self, uri=None):
     if uri is None:
         service_root = ServiceRoot()
         manager = Resource(service_root.resource.metadata["management"])
         monitor = Monitor(manager.metadata["services"]["monitor"])
         uri = monitor.resource.uri
     Service.__init__(self)
     self.bind(uri)
예제 #22
0
 def fetch_latest_stats(self):
     """ Fetch the latest server statistics as a list of 2-tuples, each
     holding a `datetime` object and a named tuple of node, relationship and
     property counts.
     """
     counts = namedtuple(
         "Stats", ("node_count", "relationship_count", "property_count"))
     uri = self.resource.metadata["resources"]["latest_data"]
     latest_data = Resource(uri).get().content
     timestamps = latest_data["timestamps"]
     data = latest_data["data"]
     data = zip(
         (datetime.fromtimestamp(t) for t in timestamps),
         (counts(*x) for x in zip(
             (numberise(n) for n in data["node_count"]),
             (numberise(n) for n in data["relationship_count"]),
             (numberise(n) for n in data["property_count"]),
         )),
     )
     return data
 def post(self, resource):
     self.__assert_unfinished()
     rs = resource.post({"statements": self.statements})
     location = rs.location
     if location:
         self.__execute = Resource(location)
     j = rs.content
     rs.close()
     self.statements = []
     if "commit" in j:
         self.__commit = Resource(j["commit"])
     if "errors" in j:
         errors = j["errors"]
         if len(errors) >= 1:
             error = errors[0]
             raise self.error_class.hydrate(error)
     out = RecordListList()
     for result in j["results"]:
         columns = result["columns"]
         producer = RecordProducer(columns)
         out.append(RecordList(columns, [producer.produce(self.graph.hydrate(r["rest"])) for r in result["data"]]))
     return out
예제 #24
0
class CypherTransaction(object):
    """ A transaction is a transient resource that allows multiple Cypher
    statements to be executed within a single server transaction.
    """

    error_class = CypherTransactionError

    def __init__(self, uri):
        log.info("begin")
        self.statements = []
        self.__begin = Resource(uri)
        self.__begin_commit = Resource(uri + "/commit")
        self.__execute = None
        self.__commit = None
        self.__finished = False
        self.graph = self.__begin.graph

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.commit()

    def __assert_unfinished(self):
        if self.__finished:
            raise Finished(self)

    @property
    def _id(self):
        """ The internal server ID of this transaction, if available.
        """
        if self.__execute is None:
            return None
        else:
            return int(self.__execute.uri.path.segments[-1])

    @property
    def finished(self):
        """ Indicates whether or not this transaction has been completed or is
        still open.

        :return: :py:const:`True` if this transaction has finished,
                 :py:const:`False` otherwise
        """
        return self.__finished

    def append(self, statement, parameters=None):
        """ Add a statement to the current queue of statements to be
        executed.

        :param statement: the statement to append
        :param parameters: a dictionary of execution parameters
        """
        self.__assert_unfinished()
        p = {}
        if parameters:
            for key, value in parameters.items():
                if isinstance(value, (Node, Rel, Relationship)):
                    value = value._id
                p[key] = value
        # OrderedDict is used here to avoid statement/parameters ordering bug
        log.info("append %r %r", statement, p)
        self.statements.append(OrderedDict([
            ("statement", statement),
            ("parameters", p),
            ("resultDataContents", ["REST"]),
        ]))

    def post(self, resource):
        self.__assert_unfinished()
        rs = resource.post({"statements": self.statements})
        location = rs.location
        if location:
            self.__execute = Resource(location)
        j = rs.content
        rs.close()
        self.statements = []
        if "commit" in j:
            self.__commit = Resource(j["commit"])
        if "errors" in j:
            errors = j["errors"]
            if len(errors) >= 1:
                error = errors[0]
                raise self.error_class.hydrate(error)
        out = RecordListList()
        for result in j["results"]:
            columns = result["columns"]
            producer = RecordProducer(columns)
            out.append(RecordList(columns, [producer.produce(self.graph.hydrate(r["rest"]))
                                            for r in result["data"]]))
        return out

    def process(self):
        """ Send all pending statements to the server for execution, leaving
        the transaction open for further statements. Along with
        :meth:`append <.CypherTransaction.append>`, this method can be used to
        batch up a number of individual statements into a single HTTP request::

            from py2neo import Graph

            graph = Graph()
            statement = "MERGE (n:Person {name:{N}}) RETURN n"

            tx = graph.cypher.begin()

            def add_names(*names):
                for name in names:
                    tx.append(statement, {"N": name})
                tx.process()

            add_names("Homer", "Marge", "Bart", "Lisa", "Maggie")
            add_names("Peter", "Lois", "Chris", "Meg", "Stewie")

            tx.commit()

        :return: list of results from pending statements
        """
        log.info("process")
        return self.post(self.__execute or self.__begin)

    def commit(self):
        """ Send all pending statements to the server for execution and commit
        the transaction.

        :return: list of results from pending statements
        """
        log.info("commit")
        try:
            return self.post(self.__commit or self.__begin_commit)
        finally:
            self.__finished = True

    def rollback(self):
        """ Rollback the current transaction.
        """
        self.__assert_unfinished()
        log.info("rollback")
        try:
            if self.__execute:
                self.__execute.delete()
        finally:
            self.__finished = True
예제 #25
0
파일: neo4j.py 프로젝트: svacha/cycli
    def relationship_types(self):
        if not self.__relationship_types:
            relationship_types_resource = Resource(self.graph.uri.string + "relationship/types")
            self.__relationship_types = sorted(list(frozenset(relationship_types_resource.get().content)))

        return self.__relationship_types
예제 #26
0
파일: neo4j.py 프로젝트: svacha/cycli
    def labels(self):
        if not self.__labels:
            labels_resource = Resource(self.graph.uri.string + "labels")
            self.__labels = sorted(list(frozenset(labels_resource.get().content)))

        return self.__labels
예제 #27
0
def test_can_remove_rewrite_uri():
    rewrite(("https", "localtoast", 4747), ("http", "localhost", 7474))
    rewrite(("https", "localtoast", 4747), None)
    assert Resource(
        "https://localtoast:4747/").uri == "https://localtoast:4747/"
예제 #28
0
class CypherTransaction(object):
    """ A transaction is a transient resource that allows multiple Cypher
    statements to be executed within a single server transaction.
    """

    error_class = CypherTransactionError

    def __init__(self, uri):
        log.info("begin")
        self.statements = []
        self.__begin = Resource(uri)
        self.__begin_commit = Resource(uri + "/commit")
        self.__execute = None
        self.__commit = None
        self.__finished = False
        self.graph = self.__begin.graph

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.commit()

    def __assert_unfinished(self):
        if self.__finished:
            raise Finished(self)

    @property
    def _id(self):
        """ The internal server ID of this transaction, if available.
        """
        if self.__execute is None:
            return None
        else:
            return int(self.__execute.uri.path.segments[-1])

    @property
    def finished(self):
        """ Indicates whether or not this transaction has been completed or is
        still open.

        :return: :py:const:`True` if this transaction has finished,
                 :py:const:`False` otherwise
        """
        return self.__finished

    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 post(self, resource):
        self.__assert_unfinished()
        rs = resource.post({"statements": self.statements})
        location = rs.location
        if location:
            self.__execute = Resource(location)
        j = rs.content
        rs.close()
        self.statements = []
        if "commit" in j:
            self.__commit = Resource(j["commit"])
        if "errors" in j:
            errors = j["errors"]
            if len(errors) >= 1:
                error = errors[0]
                raise self.error_class.hydrate(error)
        out = RecordListList()
        for result in j["results"]:
            columns = result["columns"]
            producer = RecordProducer(columns)
            out.append(
                RecordList(columns, [
                    producer.produce(self.graph.hydrate(r["rest"]))
                    for r in result["data"]
                ]))
        return out

    def process(self):
        """ Send all pending statements to the server for execution, leaving
        the transaction open for further statements. Along with
        :meth:`append <.CypherTransaction.append>`, this method can be used to
        batch up a number of individual statements into a single HTTP request::

            from py2neo import Graph

            graph = Graph()
            statement = "MERGE (n:Person {name:{N}}) RETURN n"

            tx = graph.cypher.begin()

            def add_names(*names):
                for name in names:
                    tx.append(statement, {"N": name})
                tx.process()

            add_names("Homer", "Marge", "Bart", "Lisa", "Maggie")
            add_names("Peter", "Lois", "Chris", "Meg", "Stewie")

            tx.commit()

        :return: list of results from pending statements
        """
        log.info("process")
        return self.post(self.__execute or self.__begin)

    def commit(self):
        """ Send all pending statements to the server for execution and commit
        the transaction.

        :return: list of results from pending statements
        """
        log.info("commit")
        try:
            return self.post(self.__commit or self.__begin_commit)
        finally:
            self.__finished = True

    def rollback(self):
        """ Rollback the current transaction.
        """
        self.__assert_unfinished()
        log.info("rollback")
        try:
            if self.__execute:
                self.__execute.delete()
        finally:
            self.__finished = True