aiocypher
A limited asyncio wrapper for various cypher drivers
This is not intended to be a full driver wrapper, but just to implement the things we immediately need in a relatively simple fashion, replicating the interface of the wrapped library where possible.
1# 2# 3# Copyright 2020-21 British Broadcasting Corporation 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18"""A limited asyncio wrapper for various cypher drivers 19 20This is not intended to be a full driver wrapper, but just to implement the things 21we immediately need in a relatively simple fashion, replicating the interface of the wrapped 22library where possible. 23""" 24 25from .interface.driver import Driver 26from .interface.session import Session 27from .interface.transaction import Transaction 28from .interface.result import Result 29from .interface.relationship import Relationship 30from .interface.node import Node 31from .interface.exceptions import QueryFailed 32from .empty import EmptyResult 33from .config import Config 34 35try: 36 from . import aioneo4j # noqa: F401 37except ImportError: 38 pass 39 40 41try: 42 from . import aioagensgraph # noqa: F401 43except ImportError: 44 pass 45 46 47__all__ = [ 48 'Driver', 49 'Session', 50 'Transaction', 51 'Result', 52 'Relationship', 53 'Node', 54 'EmptyResult', 55 'QueryFailed', 56 'Config' 57]
29class Driver (object, metaclass=AIOCypherABCMeta): 30 """This class encapsulates a driver object for a cypher database. Concrete subclasses specialise in 31 different databases. 32 """ 33 def __init__(self, 34 config: Config): 35 self._address = config.address 36 self._auth: Tuple[str, str] = config.auth 37 38 async def __aenter__(self) -> 'Driver': 39 return self 40 41 async def __aexit__(self, e_t, e_v, e_tb) -> Optional[bool]: 42 await self.close() 43 return False 44 45 @abstractmethod 46 def __await__(self): 47 ... 48 49 @abstractmethod 50 async def close(self) -> None: 51 """This coroutine should be awaited when the driver is no longer needed. 52 """ 53 ... 54 55 @abstractmethod 56 def session(self, **kwargs) -> AsyncContextManager[Session]: 57 """This method is used to create a Session object, which can be used as an 58 asynchronous context manager. 59 60 All interactions should be done via a Session object. Accessing the driver 61 without one is not supported. 62 """ 63 ... 64 65 @abstractmethod 66 def database_type(self) -> str: 67 ...
This class encapsulates a driver object for a cypher database. Concrete subclasses specialise in different databases.
49 @abstractmethod 50 async def close(self) -> None: 51 """This coroutine should be awaited when the driver is no longer needed. 52 """ 53 ...
This coroutine should be awaited when the driver is no longer needed.
55 @abstractmethod 56 def session(self, **kwargs) -> AsyncContextManager[Session]: 57 """This method is used to create a Session object, which can be used as an 58 asynchronous context manager. 59 60 All interactions should be done via a Session object. Accessing the driver 61 without one is not supported. 62 """ 63 ...
This method is used to create a Session object, which can be used as an asynchronous context manager.
All interactions should be done via a Session object. Accessing the driver without one is not supported.
25class Session (object, metaclass=ABCMeta): 26 """This object encapsulates a Session object. It should not be initialised directly, but 27 created via a Driver object. 28 29 It should always be used as an Async Context Manager, and using its methods outside of its 30 context may lead to undefined behaviour. 31 32 A Session object is the only supported way to interact with the cypher database. 33 """ 34 async def __aenter__(self) -> 'Session': 35 return self 36 37 async def __aexit__(self, *args) -> bool: 38 return False 39 40 @abstractmethod 41 def begin_transaction(self) -> AsyncContextManager[Transaction]: 42 """This is the main method for interacting with the Session. It 43 creates a new Transaction which is then represented by an Async Context Manager 44 """ 45 ...
This object encapsulates a Session object. It should not be initialised directly, but created via a Driver object.
It should always be used as an Async Context Manager, and using its methods outside of its context may lead to undefined behaviour.
A Session object is the only supported way to interact with the cypher database.
40 @abstractmethod 41 def begin_transaction(self) -> AsyncContextManager[Transaction]: 42 """This is the main method for interacting with the Session. It 43 creates a new Transaction which is then represented by an Async Context Manager 44 """ 45 ...
This is the main method for interacting with the Session. It creates a new Transaction which is then represented by an Async Context Manager
24class Transaction (object, metaclass=ABCMeta): 25 """A class which encapsulates a Transaction. Should never be created directly, 26 but always via a Session object. 27 28 Should always be used as an Async Context Manager. Using any of its methods outside of 29 the context may lead to undefined behaviour. 30 """ 31 async def __aenter__(self) -> "Transaction": 32 return self 33 34 async def __aexit__(self, *args): 35 return False 36 37 @abstractmethod 38 def run(self, *args, **kwargs) -> Result: 39 """This is the main routine for this class. 40 41 The actual query will not be executed until such a time as the return value (or some derivative thereof) 42 is awaited. 43 44 :returns: an Result object 45 """ 46 ...
A class which encapsulates a Transaction. Should never be created directly, but always via a Session object.
Should always be used as an Async Context Manager. Using any of its methods outside of the context may lead to undefined behaviour.
37 @abstractmethod 38 def run(self, *args, **kwargs) -> Result: 39 """This is the main routine for this class. 40 41 The actual query will not be executed until such a time as the return value (or some derivative thereof) 42 is awaited. 43 44 :returns: an Result object 45 """ 46 ...
This is the main routine for this class.
The actual query will not be executed until such a time as the return value (or some derivative thereof) is awaited.
:returns: an Result object
30class Result (Generic[R], Awaitable[R], metaclass=ABCMeta): 31 """A conceptual wrapper for a query which will return a result object of some kind. 32 33 To execute the query and return the underlying object await this object. 34 35 It also has other methods which return awaitable objects. 36 """ 37 38 @abstractmethod 39 def single(self) -> Record: 40 """Returns a Record object 41 42 Useful if the wrapped query is expected to return a single result. 43 """ 44 ... 45 46 @abstractmethod 47 async def data(self) -> List[Dict[str, Any]]: 48 """Deserialises the data in this result as a list of dictionaries and returns it. 49 """ 50 ... 51 52 @abstractmethod 53 def graph(self) -> Graph: 54 """Returns an Graph object which 55 56 Useful if the wrapped query is expected to return multiple results. 57 """ 58 ...
A conceptual wrapper for a query which will return a result object of some kind.
To execute the query and return the underlying object await this object.
It also has other methods which return awaitable objects.
38 @abstractmethod 39 def single(self) -> Record: 40 """Returns a Record object 41 42 Useful if the wrapped query is expected to return a single result. 43 """ 44 ...
Returns a Record object
Useful if the wrapped query is expected to return a single result.
46 @abstractmethod 47 async def data(self) -> List[Dict[str, Any]]: 48 """Deserialises the data in this result as a list of dictionaries and returns it. 49 """ 50 ...
Deserialises the data in this result as a list of dictionaries and returns it.
52 @abstractmethod 53 def graph(self) -> Graph: 54 """Returns an Graph object which 55 56 Useful if the wrapped query is expected to return multiple results. 57 """ 58 ...
Returns an Graph object which
Useful if the wrapped query is expected to return multiple results.
26class Relationship (Mapping[str, Union[str, int]], metaclass=ABCMeta): 27 type: str 28 start_node: Node 29 end_node: Node
A Mapping is a generic container for associating key/value pairs.
This class provides concrete generic implementations of all methods except for __getitem__, __iter__, and __len__.
Inherited Members
- collections.abc.Mapping
- get
- keys
- items
- values
24class Node (Mapping[str, Union[str, int, List[Union[str, int]]]], metaclass=ABCMeta): 25 labels: Set[str]
A Mapping is a generic container for associating key/value pairs.
This class provides concrete generic implementations of all methods except for __getitem__, __iter__, and __len__.
Inherited Members
- collections.abc.Mapping
- get
- keys
- items
- values
43class EmptyResult(Result[None]): 44 def single(self) -> Record: 45 """Returns a Record object 46 47 Useful if the wrapped query is expected to return a single result. 48 """ 49 raise RuntimeError("This result is empty") 50 51 async def data(self) -> List[Dict[str, Any]]: 52 """Deserialises the data in this result as a list of dictionaries and returns it. 53 """ 54 return [] 55 56 def graph(self) -> EmptyGraph: 57 """Returns an Graph object which 58 59 Useful if the wrapped query is expected to return multiple results. 60 """ 61 return EmptyGraph() 62 63 def __await__(self): 64 async def __inner(): 65 return None 66 return __inner().__await__()
A conceptual wrapper for a query which will return a result object of some kind.
To execute the query and return the underlying object await this object.
It also has other methods which return awaitable objects.
44 def single(self) -> Record: 45 """Returns a Record object 46 47 Useful if the wrapped query is expected to return a single result. 48 """ 49 raise RuntimeError("This result is empty")
Returns a Record object
Useful if the wrapped query is expected to return a single result.
51 async def data(self) -> List[Dict[str, Any]]: 52 """Deserialises the data in this result as a list of dictionaries and returns it. 53 """ 54 return []
Deserialises the data in this result as a list of dictionaries and returns it.
56 def graph(self) -> EmptyGraph: 57 """Returns an Graph object which 58 59 Useful if the wrapped query is expected to return multiple results. 60 """ 61 return EmptyGraph()
Returns an Graph object which
Useful if the wrapped query is expected to return multiple results.
22class QueryFailed (Exception): 23 def __init__(self, query: str, params: Dict[str, Union[str, int]]): 24 super().__init__(f"Query failed: << {query} >> with parameters {params!r}")
Common base class for all non-exit exceptions.
Inherited Members
- builtins.BaseException
- with_traceback
- add_note
- args
22class Config(NamedTuple): 23 address: str 24 username: str 25 password: str 26 27 @property 28 def auth(self) -> Tuple[str, str]: 29 return (self.username, self.password)
Config(address, username, password)
Create new instance of Config(address, username, password)
Inherited Members
- builtins.tuple
- index
- count