Exemplo n.º 1
0
def fix_parameters(parameters):
    if not parameters:
        return {}
    dehydrator = DataDehydrator()
    try:
        dehydrated, = dehydrator.dehydrate([parameters])
    except TypeError as error:
        value = error.args[0]
        raise TypeError("Parameters of type {} are not supported".format(type(value).__name__))
    else:
        return dehydrated
Exemplo n.º 2
0
    def test_dehydration_2d(self):
        coordinates = (.1, 0)
        p = CartesianPoint(coordinates)

        dehydrator = DataDehydrator()
        buffer = io.BytesIO()
        packer = Packer(buffer)
        packer.pack(dehydrator.dehydrate((p, ))[0])
        self.assertEqual(
            buffer.getvalue(),
            b"\xB3X" + b"\xC9" + struct.pack(">h", 7203) + b"".join(
                map(lambda c: b"\xC1" + struct.pack(">d", c), coordinates)))
    def test_dehydration_3d(self):
        coordinates = (1, -2, 3.1)
        p = WGS84Point(coordinates)

        dehydrator = DataDehydrator()
        buffer = io.BytesIO()
        packer = Packer(buffer)
        packer.pack(dehydrator.dehydrate((p, ))[0])
        self.assertEqual(
            buffer.getvalue(),
            b"\xB4Y" + b"\xC9" + struct.pack(">h", 4979) + b"".join(
                map(lambda c: b"\xC1" + struct.pack(">d", c), coordinates)))
Exemplo n.º 4
0
    def test_dehydration(self):
        MyPoint = point_type("MyPoint", ["x", "y"], {2: 1234})
        coordinates = (.1, 0)
        p = MyPoint(coordinates)

        dehydrator = DataDehydrator()
        buffer = io.BytesIO()
        packer = Packer(buffer)
        packer.pack(dehydrator.dehydrate((p, ))[0])
        self.assertEqual(
            buffer.getvalue(),
            b"\xB3X" + b"\xC9" + struct.pack(">h", 1234) + b"".join(
                map(lambda c: b"\xC1" + struct.pack(">d", c), coordinates)))
    def _run(self, query, parameters, db, access_mode, bookmarks,
             **kwparameters):
        query_text = str(query)  # Query or string object
        query_metadata = getattr(query, "metadata", None)
        query_timeout = getattr(query, "timeout", None)

        parameters = DataDehydrator.fix_parameters(
            dict(parameters or {}, **kwparameters))

        self._metadata = {
            "query": query_text,
            "parameters": parameters,
            "server": self._connection.server_info,
        }

        run_metadata = {
            "metadata": query_metadata,
            "timeout": query_timeout,
        }

        def on_attached(metadata):
            self._metadata.update(metadata)
            self._qid = metadata.get(
                "qid", -1
            )  # For auto-commit there is no qid and Bolt 3 do not support qid
            self._keys = metadata.get("fields")
            self._attached = True

        def on_failed_attach(metadata):
            self._metadata.update(metadata)
            self._attached = False
            self._on_closed()

        self._connection.run(
            query_text,
            parameters=parameters,
            mode=access_mode,
            bookmarks=bookmarks,
            metadata=query_metadata,
            timeout=query_timeout,
            db=db,
            on_success=on_attached,
            on_failure=on_failed_attach,
        )
        self._pull()
        self._connection.send_all()
        self._attach()
Exemplo n.º 6
0
    def run(self, cypher, parameters=None, **kwparameters):
        """ Run a Cypher statement within an auto-commit transaction.

        The statement is sent and the result header received
        immediately but the :class:`.StatementResult` content is
        fetched lazily as consumed by the client application.

        If a statement is executed before a previous
        :class:`.StatementResult` in the same :class:`.Session` has
        been fully consumed, the first result will be fully fetched
        and buffered. Note therefore that the generally recommended
        pattern of usage is to fully consume one result before
        executing a subsequent statement. If two results need to be
        consumed in parallel, multiple :class:`.Session` objects
        can be used as an alternative to result buffering.

        For more usage details, see :meth:`.Transaction.run`.

        :param cypher: Cypher statement
        :param parameters: dictionary of parameters
        :param kwparameters: additional keyword parameters
        :returns: :class:`.StatementResult` object
        """
        if not cypher:
            raise ValueError("Cannot run an empty statement")
        if not isinstance(cypher, (str, Statement)):
            raise TypeError(
                "Statement must be a string or a Statement instance")

        if not self._connection:
            self._connect(self._config.default_access_mode)
        cx = self._connection
        protocol_version = cx.PROTOCOL_VERSION
        server = cx.server

        has_transaction = self.has_transaction()

        statement_text = str(cypher)
        statement_metadata = getattr(cypher, "metadata", None)
        statement_timeout = getattr(cypher, "timeout", None)
        parameters = DataDehydrator.fix_parameters(
            dict(parameters or {}, **kwparameters))

        def fail(_):
            self._close_transaction()

        hydrant = DataHydrator()
        result_metadata = {
            "statement": statement_text,
            "parameters": parameters,
            "server": server,
            "protocol_version": protocol_version,
        }
        run_metadata = {
            "metadata": statement_metadata,
            "timeout": statement_timeout,
            "on_success": result_metadata.update,
            "on_failure": fail,
        }

        def done(summary_metadata):
            result_metadata.update(summary_metadata)
            bookmark = result_metadata.get("bookmark")
            if bookmark:
                self._bookmarks_in = tuple([bookmark])
                self._bookmark_out = bookmark

        self._last_result = result = BoltStatementResult(
            self, hydrant, result_metadata)

        if has_transaction:
            if statement_metadata:
                raise ValueError(
                    "Metadata can only be attached at transaction level")
            if statement_timeout:
                raise ValueError("Timeouts only apply at transaction level")
            # TODO: fail if explicit database name has been set
        else:
            run_metadata["bookmarks"] = self._bookmarks_in

        # TODO: capture ValueError and surface as SessionError/TransactionError if
        # TODO: explicit database selection has been made
        cx.run(statement_text, parameters, **run_metadata)
        cx.pull(
            on_records=lambda records: result._records.extend(
                hydrant.hydrate_records(result.keys(), records)),
            on_success=done,
            on_failure=fail,
            on_summary=lambda: result.detach(sync=False),
        )

        if not has_transaction:
            self._connection.send_all()
            self._connection.fetch_message()

        return result
Exemplo n.º 7
0
def dehydrated_value(value):
    return DataDehydrator.fix_parameters({"_": value})["_"]
Exemplo n.º 8
0
    def run(self, query, parameters=None, **kwparameters):
        """ Run a Cypher query within an auto-commit transaction.

        The query is sent and the result header received
        immediately but the :class:`neo4j.Result` content is
        fetched lazily as consumed by the client application.

        If a query is executed before a previous
        :class:`neo4j.Result` in the same :class:`.Session` has
        been fully consumed, the first result will be fully fetched
        and buffered. Note therefore that the generally recommended
        pattern of usage is to fully consume one result before
        executing a subsequent query. If two results need to be
        consumed in parallel, multiple :class:`.Session` objects
        can be used as an alternative to result buffering.

        For more usage details, see :meth:`.Transaction.run`.

        :param query: Cypher query
        :param parameters: dictionary of parameters
        :param kwparameters: additional keyword parameters
        :returns: :class:`neo4j.Result` object
        """
        if not query:
            raise ValueError("Cannot run an empty query")
        if not isinstance(query, (str, Query)):
            raise TypeError("query must be a string or a Query instance")

        if not self._connection:
            self._connect(self._config.default_access_mode, database=self._config.database)
        cx = self._connection
        protocol_version = cx.PROTOCOL_VERSION
        server_info = cx.server_info

        has_transaction = self.has_transaction()

        query_text = str(query)
        query_metadata = getattr(query, "metadata", None)
        query_timeout = getattr(query, "timeout", None)
        parameters = DataDehydrator.fix_parameters(dict(parameters or {}, **kwparameters))

        def fail(_):
            self._close_transaction()

        hydrant = DataHydrator()
        result_metadata = {
            "query": query_text,
            "parameters": parameters,
            "server": server_info,
            "protocol_version": protocol_version,
        }
        run_metadata = {
            "metadata": query_metadata,
            "timeout": query_timeout,
            "on_success": result_metadata.update,
            "on_failure": fail,
        }

        def done(summary_metadata):
            result_metadata.update(summary_metadata)
            bookmark = result_metadata.get("bookmark")
            if bookmark:
                self._bookmarks_in = tuple([bookmark])
                self._bookmark_out = bookmark

        self._last_result = result = Result(self, hydrant, result_metadata)

        access_mode = None
        db = None
        bookmarks = None

        if has_transaction:
            # Explicit Transaction Run does not carry any extra values. RUN "query" {parameters} {extra}
            if query_metadata:
                raise ValueError("Metadata can only be attached at transaction level")
            if query_timeout:
                raise ValueError("Timeouts only apply at transaction level")
            access_mode = None
            db = None
            bookmarks = None
        else:
            run_metadata["bookmarks"] = self._bookmarks_in
            access_mode = self._config.default_access_mode
            db = self._config.database
            bookmarks = run_metadata.get("bookmarks", self._config.bookmarks)

        # BOLT RUN
        cx.run(
            query_text,
            parameters=parameters,
            mode=access_mode,
            bookmarks=bookmarks,
            metadata=run_metadata["metadata"],
            timeout=run_metadata["timeout"],
            db=db,
            on_success=run_metadata["on_success"],
            on_failure=run_metadata["on_failure"],
        )
        # BOLT PULL
        cx.pull(
            on_records=lambda records: result._records.extend(hydrant.hydrate_records(result.keys(), records)),
            on_success=done,
            on_failure=fail,
            on_summary=lambda: result.detach(sync=False),
        )

        if not has_transaction:
            self._connection.send_all()
            self._connection.fetch_message()

        return result