Skip to content

Commit 27c36d5

Browse files
committed
Merge pull request #39 from neo4j/1.0-examples
1.0 examples
2 parents eff9108 + 32d7f9b commit 27c36d5

File tree

7 files changed

+90
-58
lines changed

7 files changed

+90
-58
lines changed

examples/test_examples.py

Lines changed: 48 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,26 @@
1919
# limitations under the License.
2020

2121

22+
from unittest import skip
23+
24+
from neo4j.v1 import TRUST_ON_FIRST_USE, TRUST_SIGNED_CERTIFICATES
2225
from test.util import ServerTestCase
2326

27+
# Do not change the contents of this tagged section without good reason*
2428
# tag::minimal-example-import[]
2529
from neo4j.v1 import GraphDatabase, basic_auth
2630
# end::minimal-example-import[]
31+
# (* "good reason" is defined as knowing what you are doing)
32+
33+
34+
auth_token = basic_auth("neo4j", "password")
2735

2836

2937
class FreshDatabaseTestCase(ServerTestCase):
3038

3139
def setUp(self):
3240
ServerTestCase.setUp(self)
33-
session = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "password")).session()
41+
session = GraphDatabase.driver("bolt://localhost", auth=auth_token).session()
3442
session.run("MATCH (n) DETACH DELETE n")
3543
session.close()
3644

@@ -42,11 +50,11 @@ def test_minimal_working_example(self):
4250
driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "password"))
4351
session = driver.session()
4452

45-
session.run("CREATE (neo:Person {name:'Neo', age:23})")
53+
session.run("CREATE (a:Person {name:'Arthur', title:'King'})", )
4654

47-
result = session.run("MATCH (p:Person) WHERE p.name = 'Neo' RETURN p.age")
55+
result = session.run("MATCH (a:Person) WHERE a.name = 'Arthur' RETURN a.name AS name, a.title AS title")
4856
while result.next():
49-
print("Neo is %d years old." % result["p.age"])
57+
print("%s %s" % (result["title"], result["name"]))
5058

5159
session.close()
5260
# end::minimal-example[]
@@ -68,40 +76,40 @@ def test_configuration(self):
6876

6977
def test_tls_require_encryption(self):
7078
# tag::tls-require-encryption[]
71-
# TODO: Unfortunately, this feature is not yet implemented for Python
72-
pass
79+
driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "password"), encrypted=True)
7380
# end::tls-require-encryption[]
7481

7582
def test_tls_trust_on_first_use(self):
7683
# tag::tls-trust-on-first-use[]
77-
# TODO: Unfortunately, this feature is not yet implemented for Python
78-
pass
84+
driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "password"), encrypted=True, trust=TRUST_ON_FIRST_USE)
7985
# end::tls-trust-on-first-use[]
86+
assert driver
8087

88+
@skip("testing verified certificates not yet supported ")
8189
def test_tls_signed(self):
8290
# tag::tls-signed[]
83-
# TODO: Unfortunately, this feature is not yet implemented for Python
84-
pass
91+
driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "password"), encrypted=True, trust=TRUST_SIGNED_CERTIFICATES)
8592
# end::tls-signed[]
93+
assert driver
8694

8795
def test_statement(self):
88-
driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "password"))
96+
driver = GraphDatabase.driver("bolt://localhost", auth=auth_token)
8997
session = driver.session()
9098
# tag::statement[]
91-
session.run("CREATE (person:Person {name: {name}})", {"name": "Neo"}).close()
99+
session.run("CREATE (person:Person {name: {name}})", {"name": "Arthur"}).close()
92100
# end::statement[]
93101
session.close()
94102

95103
def test_statement_without_parameters(self):
96-
driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "password"))
104+
driver = GraphDatabase.driver("bolt://localhost", auth=auth_token)
97105
session = driver.session()
98106
# tag::statement-without-parameters[]
99-
session.run("CREATE (person:Person {name: 'Neo'})").close()
107+
session.run("CREATE (person:Person {name: 'Arthur'})").close()
100108
# end::statement-without-parameters[]
101109
session.close()
102110

103111
def test_result_cursor(self):
104-
driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "password"))
112+
driver = GraphDatabase.driver("bolt://localhost", auth=auth_token)
105113
session = driver.session()
106114
# tag::result-cursor[]
107115
search_term = "hammer"
@@ -114,67 +122,67 @@ def test_result_cursor(self):
114122
session.close()
115123

116124
def test_cursor_nesting(self):
117-
driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "password"))
125+
driver = GraphDatabase.driver("bolt://localhost", auth=auth_token)
118126
session = driver.session()
119127
# tag::retain-result-query[]
120-
result = session.run("MATCH (person:Person) WHERE person.dept = {dept} "
121-
"RETURN id(person) AS minion", {"dept": "IT"})
128+
result = session.run("MATCH (knight:Person:Knight) WHERE knight.castle = {castle} "
129+
"RETURN id(knight) AS knight_id", {"castle": "Camelot"})
122130
while result.next():
123-
session.run("MATCH (person) WHERE id(person) = {id} "
124-
"MATCH (boss:Person) WHERE boss.name = {boss} "
125-
"CREATE (person)-[:REPORTS_TO]->(boss)", {"id": result["minion"], "boss": "Bob"})
131+
session.run("MATCH (knight) WHERE id(knight) = {id} "
132+
"MATCH (king:Person) WHERE king.name = {king} "
133+
"CREATE (knight)-[:DEFENDS]->(king)", {"id": result["knight_id"], "king": "Arthur"})
126134
# end::retain-result-query[]
127135
session.close()
128136

129137
def test_result_retention(self):
130-
driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "password"))
138+
driver = GraphDatabase.driver("bolt://localhost", auth=auth_token)
131139
session = driver.session()
132140
# tag::retain-result-process[]
133-
result = session.run("MATCH (person:Person) WHERE person.dept = {dept} "
134-
"RETURN id(person) AS minion", {"dept": "IT"})
135-
minion_records = list(result.stream())
136-
137-
for record in minion_records:
138-
session.run("MATCH (person) WHERE id(person) = {id} "
139-
"MATCH (boss:Person) WHERE boss.name = {boss} "
140-
"CREATE (person)-[:REPORTS_TO]->(boss)", {"id": record["minion"], "boss": "Bob"})
141+
result = session.run("MATCH (knight:Person:Knight) WHERE knight.castle = {castle} "
142+
"RETURN id(knight) AS knight_id", {"castle": "Camelot"})
143+
id_records = list(result.stream())
144+
145+
for record in id_records:
146+
session.run("MATCH (knight) WHERE id(knight) = {id} "
147+
"MATCH (king:Person) WHERE king.name = {king} "
148+
"CREATE (knight)-[:DEFENDS]->(king)", {"id": record["knight_id"], "king": "Arthur"})
141149
# end::retain-result-process[]
142150
session.close()
143151

144152
def test_transaction_commit(self):
145-
driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "password"))
153+
driver = GraphDatabase.driver("bolt://localhost", auth=auth_token)
146154
session = driver.session()
147155
# tag::transaction-commit[]
148156
tx = session.begin_transaction()
149-
tx.run("CREATE (p:Person {name: 'The One'})")
157+
tx.run("CREATE (:Person {name: 'Guinevere'})")
150158
tx.commit()
151159
# end::transaction-commit[]
152-
result = session.run("MATCH (p:Person {name: 'The One'}) RETURN count(p)")
160+
result = session.run("MATCH (p:Person {name: 'Guinevere'}) RETURN count(p)")
153161
assert result.next()
154162
assert result["count(p)"] == 1
155163
assert result.at_end
156164
session.close()
157165

158166
def test_transaction_rollback(self):
159-
driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "password"))
167+
driver = GraphDatabase.driver("bolt://localhost", auth=auth_token)
160168
session = driver.session()
161169
# tag::transaction-rollback[]
162170
tx = session.begin_transaction()
163-
tx.run("CREATE (p:Person {name: 'The One'})")
171+
tx.run("CREATE (:Person {name: 'Merlin'})")
164172
tx.rollback()
165173
# end::transaction-rollback[]
166-
result = session.run("MATCH (p:Person {name: 'The One'}) RETURN count(p)")
174+
result = session.run("MATCH (p:Person {name: 'Merlin'}) RETURN count(p)")
167175
assert result.next()
168176
assert result["count(p)"] == 0
169177
assert result.at_end
170178
session.close()
171179

172180
def test_result_summary_query_profile(self):
173-
driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "password"))
181+
driver = GraphDatabase.driver("bolt://localhost", auth=auth_token)
174182
session = driver.session()
175183
# tag::result-summary-query-profile[]
176184
result = session.run("PROFILE MATCH (p:Person {name: {name}}) "
177-
"RETURN id(p)", {"name": "The One"})
185+
"RETURN id(p)", {"name": "Arthur"})
178186
while result.next():
179187
pass # skip the records to get to the summary
180188
print(result.summary.statement_type)
@@ -183,10 +191,10 @@ def test_result_summary_query_profile(self):
183191
session.close()
184192

185193
def test_result_summary_notifications(self):
186-
driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "password"))
194+
driver = GraphDatabase.driver("bolt://localhost", auth=auth_token)
187195
session = driver.session()
188196
# tag::result-summary-notifications[]
189-
result = session.run("EXPLAIN MATCH (a), (b) RETURN a,b")
197+
result = session.run("EXPLAIN MATCH (king), (queen) RETURN king, queen")
190198
while result.next():
191199
pass # skip the records to get to the summary
192200
for notification in result.summary.notifications:

neo4j/v1/compat.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,39 @@
3232
try:
3333
unicode
3434
except NameError:
35+
# Python 3
36+
3537
integer = int
3638
string = str
3739

40+
def ustr(x):
41+
if isinstance(x, bytes):
42+
return x.decode("utf-8")
43+
elif isinstance(x, str):
44+
return x
45+
else:
46+
return str(x)
47+
3848
def hex2(x):
3949
if x < 0x10:
4050
return "0" + hex(x)[2:].upper()
4151
else:
4252
return hex(x)[2:].upper()
4353

4454
else:
55+
# Python 2
56+
4557
integer = (int, long)
4658
string = (str, unicode)
4759

60+
def ustr(x):
61+
if isinstance(x, str):
62+
return x.decode("utf-8")
63+
elif isinstance(x, unicode):
64+
return x
65+
else:
66+
return unicode(x)
67+
4868
def hex2(x):
4969
x = ord(x)
5070
if x < 0x10:

neo4j/v1/connection.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
from struct import pack as struct_pack, unpack as struct_unpack, unpack_from as struct_unpack_from
3434

3535
from .constants import DEFAULT_PORT, DEFAULT_USER_AGENT, KNOWN_HOSTS, MAGIC_PREAMBLE, \
36-
SECURITY_DEFAULT, SECURITY_TRUST_ON_FIRST_USE
36+
TRUST_DEFAULT, TRUST_ON_FIRST_USE
3737
from .compat import hex2
3838
from .exceptions import ProtocolError
3939
from .packstream import Packer, Unpacker
@@ -398,8 +398,8 @@ def connect(host, port=None, ssl_context=None, **config):
398398
der_encoded_server_certificate = s.getpeercert(binary_form=True)
399399
if der_encoded_server_certificate is None:
400400
raise ProtocolError("When using a secure socket, the server should always provide a certificate")
401-
security = config.get("security", SECURITY_DEFAULT)
402-
if security == SECURITY_TRUST_ON_FIRST_USE:
401+
trust = config.get("trust", TRUST_DEFAULT)
402+
if trust == TRUST_ON_FIRST_USE:
403403
store = PersonalCertificateStore()
404404
if not store.match_or_trust(host, der_encoded_server_certificate):
405405
raise ProtocolError("Server certificate does not match known certificate for %r; check "

neo4j/v1/constants.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@
3131

3232
MAGIC_PREAMBLE = 0x6060B017
3333

34-
SECURITY_NONE = 0
35-
SECURITY_TRUST_ON_FIRST_USE = 1
36-
SECURITY_VERIFIED = 2
34+
ENCRYPTED_DEFAULT = True
3735

38-
SECURITY_DEFAULT = SECURITY_TRUST_ON_FIRST_USE
36+
TRUST_ON_FIRST_USE = 0
37+
TRUST_SIGNED_CERTIFICATES = 1
38+
39+
TRUST_DEFAULT = TRUST_ON_FIRST_USE

neo4j/v1/session.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class which can be used to obtain `Driver` instances that are used for
3333

3434
from .compat import integer, string, urlparse
3535
from .connection import connect, Response, RUN, PULL_ALL
36-
from .constants import SECURITY_NONE, SECURITY_VERIFIED, SECURITY_DEFAULT
36+
from .constants import ENCRYPTED_DEFAULT, TRUST_DEFAULT, TRUST_SIGNED_CERTIFICATES
3737
from .exceptions import CypherError, ResultError
3838
from .typesystem import hydrated
3939

@@ -99,11 +99,12 @@ def __init__(self, url, **config):
9999
self.config = config
100100
self.max_pool_size = config.get("max_pool_size", DEFAULT_MAX_POOL_SIZE)
101101
self.session_pool = deque()
102-
self.security = security = config.get("security", SECURITY_DEFAULT)
103-
if security > SECURITY_NONE:
102+
self.encrypted = encrypted = config.get("encrypted", ENCRYPTED_DEFAULT)
103+
self.trust = trust = config.get("trust", TRUST_DEFAULT)
104+
if encrypted:
104105
ssl_context = SSLContext(PROTOCOL_SSLv23)
105106
ssl_context.options |= OP_NO_SSLv2
106-
if security >= SECURITY_VERIFIED:
107+
if trust >= TRUST_SIGNED_CERTIFICATES:
107108
ssl_context.verify_mode = CERT_REQUIRED
108109
ssl_context.load_default_certs(Purpose.SERVER_AUTH)
109110
self.ssl_context = ssl_context

test/tck/tck_util.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818
# See the License for the specific language governing permissions and
1919
# limitations under the License.
2020

21-
from neo4j.v1 import GraphDatabase, Relationship, Node, Path, SECURITY_NONE, basic_auth
21+
22+
from neo4j.v1 import GraphDatabase, Relationship, Node, Path, basic_auth
2223
from neo4j.v1.compat import string
2324

2425

25-
driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "password"), security=SECURITY_NONE)
26+
driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "password"), encrypted=False)
27+
2628

2729
def send_string(text):
2830
session = driver.session()

test/test_session.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from ssl import SSLSocket
2424

2525
from mock import patch
26-
from neo4j.v1.constants import SECURITY_NONE, SECURITY_TRUST_ON_FIRST_USE
26+
from neo4j.v1.constants import TRUST_ON_FIRST_USE
2727
from neo4j.v1.exceptions import CypherError, ResultError
2828
from neo4j.v1.session import GraphDatabase, basic_auth, Record, record
2929
from neo4j.v1.typesystem import Node, Relationship, Path
@@ -92,26 +92,26 @@ class SecurityTestCase(ServerTestCase):
9292

9393
def test_default_session_uses_tofu(self):
9494
driver = GraphDatabase.driver("bolt://localhost")
95-
assert driver.security == SECURITY_TRUST_ON_FIRST_USE
95+
assert driver.trust == TRUST_ON_FIRST_USE
9696

9797
def test_insecure_session_uses_normal_socket(self):
98-
driver = GraphDatabase.driver("bolt://localhost", auth=auth_token, security=SECURITY_NONE)
98+
driver = GraphDatabase.driver("bolt://localhost", auth=auth_token, encrypted=False)
9999
session = driver.session()
100100
connection = session.connection
101101
assert isinstance(connection.channel.socket, socket)
102102
assert connection.der_encoded_server_certificate is None
103103
session.close()
104104

105105
def test_tofu_session_uses_secure_socket(self):
106-
driver = GraphDatabase.driver("bolt://localhost", auth=auth_token, security=SECURITY_TRUST_ON_FIRST_USE)
106+
driver = GraphDatabase.driver("bolt://localhost", auth=auth_token, encrypted=True, trust=TRUST_ON_FIRST_USE)
107107
session = driver.session()
108108
connection = session.connection
109109
assert isinstance(connection.channel.socket, SSLSocket)
110110
assert connection.der_encoded_server_certificate is not None
111111
session.close()
112112

113113
def test_tofu_session_trusts_certificate_after_first_use(self):
114-
driver = GraphDatabase.driver("bolt://localhost", auth=auth_token, security=SECURITY_TRUST_ON_FIRST_USE)
114+
driver = GraphDatabase.driver("bolt://localhost", auth=auth_token, encrypted=True, trust=TRUST_ON_FIRST_USE)
115115
session = driver.session()
116116
connection = session.connection
117117
certificate = connection.der_encoded_server_certificate

0 commit comments

Comments
 (0)