Skip to content

Commit fb877a9

Browse files
authored
Merge pull request #186 from zhenlineo/1.5-default-config
Extract config options into default_config
2 parents a7b315b + cc365bd commit fb877a9

12 files changed

+194
-38
lines changed

neo4j/bolt/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@
2121

2222
from .cert import *
2323
from .connection import *
24-
from .response import *
24+
from .response import *

neo4j/bolt/connection.py

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -39,23 +39,15 @@
3939
from neo4j.bolt.response import InitResponse, AckFailureResponse, ResetResponse
4040
from neo4j.compat.ssl import SSL_AVAILABLE, HAS_SNI, SSLError
4141
from neo4j.exceptions import ClientError, ProtocolError, SecurityError, ServiceUnavailable
42-
from neo4j.meta import version
4342
from neo4j.packstream import Packer, Unpacker
4443
from neo4j.util import import_best as _import_best
4544
from time import clock
45+
from neo4j.config import default_config, INFINITE, TRUST_ON_FIRST_USE
4646

4747
ChunkedInputBuffer = _import_best("neo4j.bolt._io", "neo4j.bolt.io").ChunkedInputBuffer
4848
ChunkedOutputBuffer = _import_best("neo4j.bolt._io", "neo4j.bolt.io").ChunkedOutputBuffer
4949

50-
51-
INFINITE = -1
52-
DEFAULT_MAX_CONNECTION_LIFETIME = INFINITE
53-
DEFAULT_MAX_CONNECTION_POOL_SIZE = INFINITE
54-
DEFAULT_CONNECTION_TIMEOUT = 5.0
55-
DEFAULT_CONNECTION_ACQUISITION_TIMEOUT = 60
5650
DEFAULT_PORT = 7687
57-
DEFAULT_USER_AGENT = "neo4j-python/%s" % version
58-
5951
MAGIC_PREAMBLE = 0x6060B017
6052

6153

@@ -183,11 +175,11 @@ def __init__(self, address, sock, error_handler, **config):
183175
self.packer = Packer(self.output_buffer)
184176
self.unpacker = Unpacker()
185177
self.responses = deque()
186-
self._max_connection_lifetime = config.get("max_connection_lifetime", DEFAULT_MAX_CONNECTION_LIFETIME)
178+
self._max_connection_lifetime = config.get("max_connection_lifetime", default_config["max_connection_lifetime"])
187179
self._creation_timestamp = clock()
188180

189181
# Determine the user agent and ensure it is a Unicode value
190-
user_agent = config.get("user_agent", DEFAULT_USER_AGENT)
182+
user_agent = config.get("user_agent", default_config["user_agent"])
191183
if isinstance(user_agent, bytes):
192184
user_agent = user_agent.decode("UTF-8")
193185
self.user_agent = user_agent
@@ -413,8 +405,8 @@ def __init__(self, connector, connection_error_handler, **config):
413405
self.connections = {}
414406
self.lock = RLock()
415407
self.cond = Condition(self.lock)
416-
self._max_connection_pool_size = config.get("max_connection_pool_size", DEFAULT_MAX_CONNECTION_POOL_SIZE)
417-
self._connection_acquisition_timeout = config.get("connection_acquisition_timeout", DEFAULT_CONNECTION_ACQUISITION_TIMEOUT)
408+
self._max_connection_pool_size = config.get("max_connection_pool_size", default_config["max_connection_pool_size"])
409+
self._connection_acquisition_timeout = config.get("connection_acquisition_timeout", default_config["connection_acquisition_timeout"])
418410

419411
def __enter__(self):
420412
return self
@@ -546,10 +538,10 @@ def connect(address, ssl_context=None, error_handler=None, **config):
546538
else:
547539
raise ValueError("Unsupported address {!r}".format(address))
548540
t = s.gettimeout()
549-
s.settimeout(config.get("connection_timeout", DEFAULT_CONNECTION_TIMEOUT))
541+
s.settimeout(config.get("connection_timeout", default_config["connection_timeout"]))
550542
s.connect(address)
551543
s.settimeout(t)
552-
s.setsockopt(SOL_SOCKET, SO_KEEPALIVE, 1 if config.get("keep_alive", True) else 0)
544+
s.setsockopt(SOL_SOCKET, SO_KEEPALIVE, 1 if config.get("keep_alive", default_config["keep_alive"]) else 0)
553545
except SocketTimeout:
554546
if s:
555547
try:
@@ -582,14 +574,13 @@ def connect(address, ssl_context=None, error_handler=None, **config):
582574
error.__cause__ = cause
583575
raise error
584576
else:
585-
from neo4j.v1 import TRUST_DEFAULT, TRUST_ON_FIRST_USE
586577
# Check that the server provides a certificate
587578
der_encoded_server_certificate = s.getpeercert(binary_form=True)
588579
if der_encoded_server_certificate is None:
589580
s.close()
590581
raise ProtocolError("When using a secure socket, the server should always "
591582
"provide a certificate")
592-
trust = config.get("trust", TRUST_DEFAULT)
583+
trust = config.get("trust", default_config["trust"])
593584
if trust == TRUST_ON_FIRST_USE:
594585
from neo4j.bolt.cert import PersonalCertificateStore
595586
store = PersonalCertificateStore()

neo4j/config.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/usr/bin/env python
2+
# -*- encoding: utf-8 -*-
3+
4+
# Copyright (c) 2002-2017 "Neo Technology,"
5+
# Network Engine for Objects in Lund AB [http://neotechnology.com]
6+
#
7+
# This file is part of Neo4j.
8+
#
9+
# Licensed under the Apache License, Version 2.0 (the "License");
10+
# you may not use this file except in compliance with the License.
11+
# You may obtain a copy of the License at
12+
#
13+
# http://www.apache.org/licenses/LICENSE-2.0
14+
#
15+
# Unless required by applicable law or agreed to in writing, software
16+
# distributed under the License is distributed on an "AS IS" BASIS,
17+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
# See the License for the specific language governing permissions and
19+
# limitations under the License.
20+
21+
from neo4j.meta import version
22+
23+
# Auth
24+
TRUST_ON_FIRST_USE = 0 # Deprecated
25+
TRUST_SIGNED_CERTIFICATES = 1 # Deprecated
26+
TRUST_ALL_CERTIFICATES = 2
27+
TRUST_CUSTOM_CA_SIGNED_CERTIFICATES = 3
28+
TRUST_SYSTEM_CA_SIGNED_CERTIFICATES = 4
29+
TRUST_DEFAULT = TRUST_ALL_CERTIFICATES
30+
31+
# Connection Pool Management
32+
INFINITE = -1
33+
DEFAULT_MAX_CONNECTION_LIFETIME = 3600 # 1h
34+
DEFAULT_MAX_CONNECTION_POOL_SIZE = 100
35+
DEFAULT_CONNECTION_TIMEOUT = 5.0 # 5s
36+
37+
# Connection Settings
38+
DEFAULT_CONNECTION_ACQUISITION_TIMEOUT = 60 # 1m
39+
40+
# Routing settings
41+
DEFAULT_MAX_RETRY_TIME = 30.0 # 30s
42+
43+
LOAD_BALANCING_STRATEGY_LEAST_CONNECTED = 0
44+
LOAD_BALANCING_STRATEGY_ROUND_ROBIN = 1
45+
DEFAULT_LOAD_BALANCING_STRATEGY = LOAD_BALANCING_STRATEGY_LEAST_CONNECTED
46+
47+
# Client name
48+
DEFAULT_USER_AGENT = "neo4j-python/%s" % version
49+
50+
default_config = {
51+
"auth": None, # provide your own authentication token such as {"username", "password"}
52+
"encrypted": True,
53+
"trust": TRUST_DEFAULT,
54+
"der-encoded_server_certificate": None,
55+
56+
"user_agent": DEFAULT_USER_AGENT,
57+
58+
# Connection pool management
59+
"max_connection_lifetime": DEFAULT_MAX_CONNECTION_LIFETIME,
60+
"max_connection_pool_size": DEFAULT_MAX_CONNECTION_POOL_SIZE,
61+
"connection_acquisition_timeout": DEFAULT_CONNECTION_ACQUISITION_TIMEOUT,
62+
63+
# Connection settings:
64+
"connection_timeout": DEFAULT_CONNECTION_TIMEOUT,
65+
"keep_alive": True,
66+
67+
# Routing settings:
68+
"max_retry_time": DEFAULT_MAX_RETRY_TIME,
69+
"load_balancing_strategy": DEFAULT_LOAD_BALANCING_STRATEGY
70+
}

neo4j/v1/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
from .exceptions import *
2424
from .result import *
2525
from .routing import *
26-
from .session import *
2726
from .security import *
27+
from .session import *
2828
from .types import *
2929

3030
# Register supported URI schemes

neo4j/v1/api.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from neo4j.exceptions import ProtocolError, ServiceUnavailable
2929
from neo4j.compat import urlparse
3030
from neo4j.exceptions import CypherError, TransientError
31+
from neo4j.config import default_config
3132

3233
from .exceptions import DriverError, SessionError, SessionExpired, TransactionError
3334

@@ -36,12 +37,10 @@
3637
READ_ACCESS = "READ"
3738
WRITE_ACCESS = "WRITE"
3839

39-
DEFAULT_MAX_RETRY_TIME = 30.0
4040
INITIAL_RETRY_DELAY = 1.0
4141
RETRY_DELAY_MULTIPLIER = 2.0
4242
RETRY_DELAY_JITTER_FACTOR = 0.2
4343

44-
4544
def last_bookmark(b0, b1):
4645
""" Return the latest of two bookmarks by looking for the maximum
4746
integer value following the last colon in the bookmark string.
@@ -114,6 +113,8 @@ def driver(cls, uri, **config):
114113
`user_agent`
115114
A custom user agent string, if required.
116115
116+
for more config options see neo4j.config.default_config
117+
117118
"""
118119
parsed = urlparse(uri)
119120
try:
@@ -145,7 +146,7 @@ class Driver(object):
145146
def __init__(self, pool, **config):
146147
self._lock = RLock()
147148
self._pool = pool
148-
self._max_retry_time = config.get("max_retry_time", DEFAULT_MAX_RETRY_TIME)
149+
self._max_retry_time = config.get("max_retry_time", default_config["max_retry_time"])
149150

150151
def __del__(self):
151152
self.close()
@@ -233,7 +234,7 @@ class Session(object):
233234
_bookmarks = ()
234235

235236
# Default maximum time to keep retrying failed transactions.
236-
_max_retry_time = DEFAULT_MAX_RETRY_TIME
237+
_max_retry_time = default_config["max_retry_time"]
237238

238239
_closed = False
239240

neo4j/v1/routing.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,7 @@
3131
from neo4j.v1.exceptions import SessionExpired
3232
from neo4j.v1.security import SecurityPlan
3333
from neo4j.v1.session import BoltSession
34-
35-
LOAD_BALANCING_STRATEGY_LEAST_CONNECTED = 0
36-
LOAD_BALANCING_STRATEGY_ROUND_ROBIN = 1
37-
DEFAULT_LOAD_BALANCING_STRATEGY = LOAD_BALANCING_STRATEGY_LEAST_CONNECTED
34+
from neo4j.config import default_config, LOAD_BALANCING_STRATEGY_LEAST_CONNECTED, LOAD_BALANCING_STRATEGY_ROUND_ROBIN
3835

3936

4037
class OrderedSet(MutableSet):
@@ -166,7 +163,7 @@ class LoadBalancingStrategy(object):
166163

167164
@classmethod
168165
def build(cls, connection_pool, **config):
169-
load_balancing_strategy = config.get("load_balancing_strategy", DEFAULT_LOAD_BALANCING_STRATEGY)
166+
load_balancing_strategy = config.get("load_balancing_strategy", default_config["load_balancing_strategy"])
170167
if load_balancing_strategy == LOAD_BALANCING_STRATEGY_LEAST_CONNECTED:
171168
return LeastConnectedLoadBalancingStrategy(connection_pool)
172169
elif load_balancing_strategy == LOAD_BALANCING_STRATEGY_ROUND_ROBIN:

neo4j/v1/security.py

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,12 @@
2121
from warnings import warn
2222

2323
from neo4j.compat.ssl import SSL_AVAILABLE, SSLContext, PROTOCOL_SSLv23, OP_NO_SSLv2, CERT_REQUIRED
24-
24+
from neo4j.config import default_config, TRUST_ALL_CERTIFICATES, TRUST_CUSTOM_CA_SIGNED_CERTIFICATES, TRUST_ON_FIRST_USE, TRUST_SIGNED_CERTIFICATES, TRUST_SYSTEM_CA_SIGNED_CERTIFICATES
2525

2626
ENCRYPTION_OFF = 0
2727
ENCRYPTION_ON = 1
2828
ENCRYPTION_DEFAULT = ENCRYPTION_ON if SSL_AVAILABLE else ENCRYPTION_OFF
2929

30-
TRUST_ON_FIRST_USE = 0 # Deprecated
31-
TRUST_SIGNED_CERTIFICATES = 1 # Deprecated
32-
TRUST_ALL_CERTIFICATES = 2
33-
TRUST_CUSTOM_CA_SIGNED_CERTIFICATES = 3
34-
TRUST_SYSTEM_CA_SIGNED_CERTIFICATES = 4
35-
TRUST_DEFAULT = TRUST_ALL_CERTIFICATES
36-
3730

3831
class AuthToken(object):
3932
""" Container for auth information
@@ -56,10 +49,10 @@ class SecurityPlan(object):
5649

5750
@classmethod
5851
def build(cls, **config):
59-
encrypted = config.get("encrypted", None)
52+
encrypted = config.get("encrypted", default_config["encrypted"])
6053
if encrypted is None:
6154
encrypted = _encryption_default()
62-
trust = config.get("trust", TRUST_DEFAULT)
55+
trust = config.get("trust", default_config["trust"])
6356
if encrypted:
6457
if not SSL_AVAILABLE:
6558
raise RuntimeError("Bolt over TLS is only available in Python 2.7.9+ and "
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/usr/bin/env python
2+
# -*- encoding: utf-8 -*-
3+
4+
# Copyright (c) 2002-2017 "Neo Technology,"
5+
# Network Engine for Objects in Lund AB [http://neotechnology.com]
6+
#
7+
# This file is part of Neo4j.
8+
#
9+
# Licensed under the Apache License, Version 2.0 (the "License");
10+
# you may not use this file except in compliance with the License.
11+
# You may obtain a copy of the License at
12+
#
13+
# http://www.apache.org/licenses/LICENSE-2.0
14+
#
15+
# Unless required by applicable law or agreed to in writing, software
16+
# distributed under the License is distributed on an "AS IS" BASIS,
17+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
# See the License for the specific language governing permissions and
19+
# limitations under the License.
20+
21+
# tag::config-connection-pool-import[]
22+
from neo4j.v1 import GraphDatabase
23+
# end::config-connection-pool-import[]
24+
25+
26+
class ConfigConnectionPoolExample:
27+
# tag::config-connection-pool[]
28+
def __init__(self, uri, user, password):
29+
self._driver = GraphDatabase.driver(uri, auth=(user, password),
30+
max_connection_lifetime=30 * 60, max_connection_pool_size=50,
31+
connection_acquisition_timeout=2 * 60)
32+
# end::config-connection-pool[]
33+
34+
def close(self):
35+
self._driver.close()
36+
37+
def can_connect(driver):
38+
result = driver.session().run("RETURN 1")
39+
return result.single()[0] == 1

test/examples/config_connection_timeout_example.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,7 @@ def __init__(self, uri, user, password):
3131

3232
def close(self):
3333
self._driver.close()
34+
35+
def can_connect(self):
36+
result = self._driver.session().run("RETURN 1")
37+
return result.single()[0] == 1
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/usr/bin/env python
2+
# -*- encoding: utf-8 -*-
3+
4+
# Copyright (c) 2002-2017 "Neo Technology,"
5+
# Network Engine for Objects in Lund AB [http://neotechnology.com]
6+
#
7+
# This file is part of Neo4j.
8+
#
9+
# Licensed under the Apache License, Version 2.0 (the "License");
10+
# you may not use this file except in compliance with the License.
11+
# You may obtain a copy of the License at
12+
#
13+
# http://www.apache.org/licenses/LICENSE-2.0
14+
#
15+
# Unless required by applicable law or agreed to in writing, software
16+
# distributed under the License is distributed on an "AS IS" BASIS,
17+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
# See the License for the specific language governing permissions and
19+
# limitations under the License.
20+
21+
# tag::config-load-balancing-strategy-import[]
22+
from neo4j.v1 import GraphDatabase, LOAD_BALANCING_STRATEGY_LEAST_CONNECTED
23+
# end::config-load-balancing-strategy-import[]
24+
25+
26+
class ConfigLoadBalancingStrategyExample:
27+
# tag::config-load-balancing-strategy[]
28+
def __init__(self, uri, user, password):
29+
self._driver = GraphDatabase.driver(uri, auth=(user, password), load_balancing_strategy=LOAD_BALANCING_STRATEGY_LEAST_CONNECTED)
30+
# end::config-load-balancing-strategy[]
31+
32+
def close(self):
33+
self._driver.close()
34+
35+
def can_connect(self):
36+
result = self._driver.session().run("RETURN 1")
37+
return result.single()[0] == 1

test/examples/config_max_retry_time_example.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,7 @@ def __init__(self, uri, user, password):
3131

3232
def close(self):
3333
self._driver.close()
34+
35+
def can_connect(self):
36+
result = self._driver.session().run("RETURN 1")
37+
return result.single()[0] == 1

test/examples/test_examples.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,26 @@ def test_autocommit_transaction_example(self):
5252

5353
self.assertTrue(self.person_count('Alice') > 0)
5454

55+
def test_config_connection_pool_example(self):
56+
from test.examples.config_connection_pool_example import ConfigConnectionPoolExample
57+
example = ConfigConnectionPoolExample(self.bolt_uri, self.user, self.password)
58+
self.assertTrue(example.can_connect())
59+
60+
def test_connection_timeout_example(self):
61+
from test.examples.config_connection_timeout_example import ConfigConnectionTimeoutExample
62+
example = ConfigConnectionTimeoutExample(self.bolt_uri, self.user, self.password)
63+
self.assertTrue(example.can_connect())
64+
65+
def test_load_balancing_strategy_example(self):
66+
from test.examples.config_load_balancing_strategy_example import ConfigLoadBalancingStrategyExample
67+
example = ConfigLoadBalancingStrategyExample(self.bolt_uri, self.user, self.password)
68+
self.assertTrue(example.can_connect())
69+
70+
def test_max_retry_time_example(self):
71+
from test.examples.config_max_retry_time_example import ConfigMaxRetryTimeExample
72+
example = ConfigMaxRetryTimeExample(self.bolt_uri, self.user, self.password)
73+
self.assertTrue(example.can_connect())
74+
5575
def test_basic_auth_example(self):
5676
from test.examples.auth_example import BasicAuthExample
5777

0 commit comments

Comments
 (0)