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
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)))
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()
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
def dehydrated_value(value): return DataDehydrator.fix_parameters({"_": value})["_"]
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