1414# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1515# See the License for the specific language governing permissions and
1616# limitations under the License.
17+
18+
19+ import asyncio
20+ import traceback
1721from inspect import (
1822 getmembers ,
1923 isfunction ,
2024)
21- import io
22- from json import loads , dumps
23- import logging
24- import sys
25- import traceback
26-
27- from neo4j ._exceptions import (
28- BoltError
25+ from json import (
26+ dumps ,
27+ loads ,
2928)
29+ from pathlib import Path
30+
31+ from neo4j ._exceptions import BoltError
3032from neo4j .exceptions import (
3133 DriverError ,
3234 Neo4jError ,
3335 UnsupportedServerProduct ,
3436)
3537
36- import testkitbackend .requests as requests
37-
38- buffer_handler = logging .StreamHandler (io .StringIO ())
39- buffer_handler .setLevel (logging .DEBUG )
38+ from ._driver_logger import (
39+ buffer_handler ,
40+ log ,
41+ )
42+ from .exceptions import MarkdAsDriverException
43+ from . import requests
4044
41- handler = logging .StreamHandler (sys .stdout )
42- handler .setLevel (logging .DEBUG )
43- logging .getLogger ("neo4j" ).addHandler (handler )
44- logging .getLogger ("neo4j" ).addHandler (buffer_handler )
45- logging .getLogger ("neo4j" ).setLevel (logging .DEBUG )
4645
47- log = logging .getLogger ("testkitbackend" )
48- log .addHandler (handler )
49- log .setLevel (logging .DEBUG )
46+ TESTKIT_BACKEND_PATH = Path (__file__ ).absolute ().resolve ().parent
47+ DRIVER_PATH = TESTKIT_BACKEND_PATH .parent / "neo4j"
5048
5149
5250class Request (dict ):
@@ -134,6 +132,41 @@ def process_request(self):
134132 request = request + line
135133 return False
136134
135+ @staticmethod
136+ def _exc_stems_from_driver (exc ):
137+ stack = traceback .extract_tb (exc .__traceback__ )
138+ for frame in stack [- 1 :1 :- 1 ]:
139+ p = Path (frame .filename )
140+ if TESTKIT_BACKEND_PATH in p .parents :
141+ return False
142+ if DRIVER_PATH in p .parents :
143+ return True
144+
145+ def write_driver_exc (self , exc ):
146+ log .debug (traceback .format_exc ())
147+
148+ key = self .next_key ()
149+ self .errors [key ] = exc
150+
151+ payload = {"id" : key , "msg" : "" }
152+
153+ if isinstance (exc , MarkdAsDriverException ):
154+ wrapped_exc = exc .wrapped_exc
155+ payload ["errorType" ] = str (type (wrapped_exc ))
156+ if wrapped_exc .args :
157+ payload ["msg" ] = str (wrapped_exc .args [0 ])
158+ else :
159+ payload ["errorType" ] = str (type (exc ))
160+ if isinstance (exc , Neo4jError ) and exc .message is not None :
161+ payload ["msg" ] = str (exc .message )
162+ elif exc .args :
163+ payload ["msg" ] = str (exc .args [0 ])
164+
165+ if isinstance (exc , Neo4jError ):
166+ payload ["code" ] = exc .code
167+
168+ self .send_response ("DriverError" , payload )
169+
137170 def _process (self , request ):
138171 """ Process a received request by retrieving handler that
139172 corresponds to the request name.
@@ -156,34 +189,25 @@ def _process(self, request):
156189 " request: " + ", " .join (unsused_keys )
157190 )
158191 except (Neo4jError , DriverError , UnsupportedServerProduct ,
159- BoltError ) as e :
160- log .debug (traceback .format_exc ())
161- if isinstance (e , Neo4jError ):
162- msg = "" if e .message is None else str (e .message )
163- else :
164- msg = str (e .args [0 ]) if e .args else ""
165-
166- key = self .next_key ()
167- self .errors [key ] = e
168- payload = {"id" : key , "errorType" : str (type (e )), "msg" : msg }
169- if isinstance (e , Neo4jError ):
170- payload ["code" ] = e .code
171- self .send_response ("DriverError" , payload )
192+ BoltError , MarkdAsDriverException ) as e :
193+ self .write_driver_exc (e )
172194 except requests .FrontendError as e :
173195 self .send_response ("FrontendError" , {"msg" : str (e )})
174- except Exception :
175- tb = traceback .format_exc ()
176- log .error (tb )
177- self .send_response ("BackendError" , {"msg" : tb })
196+ except Exception as e :
197+ if self ._exc_stems_from_driver (e ):
198+ self .write_driver_exc (e )
199+ else :
200+ tb = traceback .format_exc ()
201+ log .error (tb )
202+ self .send_response ("BackendError" , {"msg" : tb })
178203
179204 def send_response (self , name , data ):
180205 """ Sends a response to backend.
181206 """
182- buffer_handler .acquire ()
183- log_output = buffer_handler .stream .getvalue ()
184- buffer_handler .stream .truncate (0 )
185- buffer_handler .stream .seek (0 )
186- buffer_handler .release ()
207+ with buffer_handler .lock :
208+ log_output = buffer_handler .stream .getvalue ()
209+ buffer_handler .stream .truncate (0 )
210+ buffer_handler .stream .seek (0 )
187211 if not log_output .endswith ("\n " ):
188212 log_output += "\n "
189213 self ._wr .write (log_output .encode ("utf-8" ))
@@ -193,4 +217,7 @@ def send_response(self, name, data):
193217 self ._wr .write (b"#response begin\n " )
194218 self ._wr .write (bytes (response + "\n " , "utf-8" ))
195219 self ._wr .write (b"#response end\n " )
196- self ._wr .flush ()
220+ if isinstance (self ._wr , asyncio .StreamWriter ):
221+ self ._wr .drain ()
222+ else :
223+ self ._wr .flush ()
0 commit comments