@@ -33,7 +33,7 @@ class which can be used to obtain `Driver` instances that are used for
3333from .compat import integer , string , urlparse
3434from .connection import connect , Response , RUN , PULL_ALL
3535from .constants import ENCRYPTED_DEFAULT , TRUST_DEFAULT , TRUST_SIGNED_CERTIFICATES
36- from .exceptions import CypherError , ResultError
36+ from .exceptions import CypherError , ProtocolError , ResultError
3737from .ssl_compat import SSL_AVAILABLE , SSLContext , PROTOCOL_SSLv23 , OP_NO_SSLv2 , CERT_REQUIRED
3838from .types import hydrated
3939
@@ -107,7 +107,8 @@ def __init__(self, url, **config):
107107 self .host = parsed .hostname
108108 self .port = parsed .port
109109 else :
110- raise ValueError ("Unsupported URL scheme: %s" % parsed .scheme )
110+ raise ProtocolError ("Unsupported URI scheme: '%s' in url: '%s'. Currently only supported 'bolt'." %
111+ (parsed .scheme , url ))
111112 self .config = config
112113 self .max_pool_size = config .get ("max_pool_size" , DEFAULT_MAX_POOL_SIZE )
113114 self .session_pool = deque ()
@@ -239,7 +240,7 @@ def keys(self):
239240 # Fetch messages until we have the header or a failure
240241 while self ._keys is None and not self ._consumed :
241242 self .connection .fetch ()
242- return self ._keys
243+ return tuple ( self ._keys )
243244
244245 def buffer (self ):
245246 if self .connection and not self .connection .closed :
@@ -262,9 +263,9 @@ def single(self):
262263 records = list (self )
263264 num_records = len (records )
264265 if num_records == 0 :
265- raise ResultError ("No records found in stream " )
266+ raise ResultError ("Cannot retrieve a single record, because this result is empty. " )
266267 elif num_records != 1 :
267- raise ResultError ("Multiple records found in stream " )
268+ raise ResultError ("Expected a result with a single record, but this result contains at least one more. " )
268269 else :
269270 return records [0 ]
270271
@@ -396,7 +397,6 @@ def contains_updates(self):
396397#: a list of sub-plans
397398Plan = namedtuple ("Plan" , ("operator_type" , "identifiers" , "arguments" , "children" ))
398399
399-
400400#: A profiled plan describes how the database executed your statement.
401401#:
402402#: db_hits:
@@ -484,7 +484,12 @@ def run(self, statement, parameters=None):
484484 :return: Cypher result
485485 :rtype: :class:`.StatementResult`
486486 """
487+ if self .transaction :
488+ raise ProtocolError ("Statements cannot be run directly on a session with an open transaction;"
489+ " either run from within the transaction or use a different session." )
490+ return self ._run (statement , parameters )
487491
492+ def _run (self , statement , parameters = None ):
488493 # Ensure the statement is a Unicode value
489494 if isinstance (statement , bytes ):
490495 statement = statement .decode ("UTF-8" )
@@ -517,14 +522,18 @@ def close(self):
517522 """
518523 if self .last_result :
519524 self .last_result .buffer ()
525+ if self .transaction :
526+ self .transaction .close ()
520527 self .driver .recycle (self )
521528
522529 def begin_transaction (self ):
523530 """ Create a new :class:`.Transaction` within this session.
524531
525532 :return: new :class:`.Transaction` instance.
526533 """
527- assert not self .transaction
534+ if self .transaction :
535+ raise ProtocolError ("You cannot begin a transaction on a session with an open transaction;"
536+ " either run from within the transaction or use a different session." )
528537 self .transaction = Transaction (self )
529538 return self .transaction
530539
@@ -552,7 +561,7 @@ class Transaction(object):
552561
553562 def __init__ (self , session ):
554563 self .session = session
555- self .session .run ("BEGIN" )
564+ self .session ._run ("BEGIN" )
556565
557566 def __enter__ (self ):
558567 return self
@@ -570,7 +579,7 @@ def run(self, statement, parameters=None):
570579 :return:
571580 """
572581 assert not self .closed
573- return self .session .run (statement , parameters )
582+ return self .session ._run (statement , parameters )
574583
575584 def commit (self ):
576585 """ Mark this transaction as successful and close in order to
@@ -591,9 +600,9 @@ def close(self):
591600 """
592601 assert not self .closed
593602 if self .success :
594- self .session .run ("COMMIT" )
603+ self .session ._run ("COMMIT" )
595604 else :
596- self .session .run ("ROLLBACK" )
605+ self .session ._run ("ROLLBACK" )
597606 self .closed = True
598607 self .session .transaction = None
599608
0 commit comments