I'm trying to set a backend using py2neo on google app engine. It works just fine when pushed on the dev on app engine, however, unfortunately, it doesn't work when I use it on localhost.
First, i've setted the HOME environment variable in python (thanks to that tip, my code works on my dev) but it doesn't fix the localhost problem
Then, i've followed that advice "ImportError: No module named _ssl" with dev_appserver.py from Google App Engine it prevents one exception but another rises after.
Here is my traceback
ft1.1: Traceback (most recent call last):
File "/Users/Arnaud/Documents/project/app/test/neo4j/test_graph_handler.py", line 13, in test_get_direct_neighbours
selection = self.graph_handler.get_direct_neighbours("8")
File "/Users/Arnaud/Documents/project/app/neo4j/graph_handler.py", line 20, in get_direct_neighbours
labels(l) AS `relationship`" % self.protect(ean))
File "/Users/Arnaud/Documents/project/app/libs/py2neo/database/__init__.py", line 694, in run
return self.begin(autocommit=True).run(statement, parameters, **kwparameters)
File "/Users/Arnaud/Documents/project/app/libs/py2neo/database/__init__.py", line 370, in begin
return self.transaction_class(self, autocommit)
File "/Users/Arnaud/Documents/project/app/libs/py2neo/database/__init__.py", line 1212, in __init__
self.session = driver.session()
File "/Users/Arnaud/Documents/project/app/libs/py2neo/packages/neo4j/v1/session.py", line 126, in session
connection = connect(self.address, self.ssl_context, **self.config)
File "/Users/Arnaud/Documents/project/app/libs/py2neo/packages/neo4j/v1/bolt.py", line 444, in connect
if not store.match_or_trust(host, der_encoded_server_certificate):
File "/Users/Arnaud/Documents/project/app/libs/py2neo/packages/neo4j/v1/bolt.py", line 397, in match_or_trust
f_out = os_open(self.path, O_CREAT | O_APPEND | O_WRONLY, 0o600) # TODO: Windows
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/devappserver2/python/stubs.py", line 73, in fake_open
raise OSError(errno.EROFS, 'Read-only file system', filename)
OSError: [Errno 30] Read-only file system: '/Users/Arnaud/.neo4j/known_hosts'
As everything lauches in a sandboxed environnement and with a fake user, the exception is normal but it does not happen on the dev.
And here is /Users/Arnaud/Documents/project/app/neo4j/graph_handler.py:20
13 def get_direct_neighbours(self, ean):
14 selection = self.graph.run("\
15 MATCH\
16 (:Product {ean: '%s'})-->(l)<--(n:Product)\
17 RETURN\
18 n.ean AS `ean`,\
19 n.name AS `name`,\
20 labels(l) AS `relationship`" % self.protect(ean))
21 return selection
So to understand why it would work on the dev, I tried to localize where sandbox and dev execution start being different. and it is right here in /Users/Arnaud/Documents/project/app/libs/py2neo/packages/neo4j/v1/bolt.py:427
427 if ssl_context and SSL_AVAILABLE:
428 host, port = host_port
429 if __debug__: log_info("~~ [SECURE] %s", host)
430 try:
431 s = ssl_context.wrap_socket(s, server_hostname=host if HAS_SNI else None)
432 except SSLError as cause:
433 error = ProtocolError("Cannot establish secure connection; %s" % cause.args[1])
434 error.__cause__ = cause
435 raise error
436 else:
437 # Check that the server provides a certificate
438 der_encoded_server_certificate = s.getpeercert(binary_form=True)
439 if der_encoded_server_certificate is None:
440 raise ProtocolError("When using a secure socket, the server should always provide a certificate")
441 trust = config.get("trust", TRUST_DEFAULT)
442 if trust == TRUST_ON_FIRST_USE:
443 store = PersonalCertificateStore()
444 if not store.match_or_trust(host, der_encoded_server_certificate):
445 raise ProtocolError("Server certificate does not match known certificate for %r; check "
446 "details in file %r" % (host, KNOWN_HOSTS))
447 else:
448 der_encoded_server_certificate = None
Because in the dev, ssl loading fails in ssl_compat.py while on localhost, it succeeds and so the code goes inside the if statement and fails at line 444
To understand that I forced SSL_AVAILABLE to be falsy, however even with that I have wierd problems about app engine sockets which are not recognized as sockets
ft1.1: Traceback (most recent call last):
File "/Users/Arnaud/Documents/project/app/test/neo4j/test_graph_handler.py", line 13, in test_get_direct_neighbours
selection = self.graph_handler.get_direct_neighbours("8")
File "/Users/Arnaud/Documents/project/app/neo4j/graph_handler.py", line 20, in get_direct_neighbours
labels(l) AS `relationship`" % self.protect(ean))
File "/Users/Arnaud/Documents/project/app/libs/py2neo/database/__init__.py", line 694, in run
return self.begin(autocommit=True).run(statement, parameters, **kwparameters)
File "/Users/Arnaud/Documents/project/app/libs/py2neo/database/__init__.py", line 370, in begin
return self.transaction_class(self, autocommit)
File "/Users/Arnaud/Documents/project/app/libs/py2neo/database/__init__.py", line 1212, in __init__
self.session = driver.session()
File "/Users/Arnaud/Documents/project/app/libs/py2neo/packages/neo4j/v1/session.py", line 126, in session
connection = connect(self.address, self.ssl_context, **self.config)
File "/Users/Arnaud/Documents/project/app/libs/py2neo/packages/neo4j/v1/bolt.py", line 460, in connect
ready_to_read, _, _ = select((s,), (), (), 0)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/remote_socket/_remote_socket.py", line 483, in select
_SetState(request, _GetSocket(value), POLLIN)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/remote_socket/_remote_socket.py", line 425, in _GetSocket
raise ValueError('select only supported on socket objects.')
ValueError: select only supported on socket objects.
If anyone have faced the same issues, I would be interested in that because having to push on the dev before any test quite painful.
EDIT: For those who would want to know, as I have no answer from nigel yet and I needed some fast solution, i've created my own class to send and recieve cypher requests, it's compatible with app engine and i've putted it on a gist: https://gist.github.com/ArnaudParan/e26f291ba8b3c08e5b762d549667c7d6 It's experimental and might not work if you ask for full nodes but if it can help, i publish it