pyneoinstance 4.0.2__tar.gz → 4.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyneoinstance-4.0.2/pyneoinstance.egg-info → pyneoinstance-4.0.3}/PKG-INFO +1 -1
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/__init__.py +1 -1
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/database/neo4jdbms.py +22 -5
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3/pyneoinstance.egg-info}/PKG-INFO +1 -1
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance.egg-info/SOURCES.txt +0 -2
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyproject.toml +1 -1
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/test/test_neo4jdb.py +30 -0
- pyneoinstance-4.0.2/test/__init__.py +0 -3
- pyneoinstance-4.0.2/test/context.py +0 -8
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/LICENSE +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/MANIFEST.in +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/README.md +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/database/__init__.py +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/database/context.py +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/fileload/__init__.py +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/fileload/helpers.py +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/fileload/loadyaml.py +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/py.typed +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/util/__init__.py +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/util/functions.py +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance.egg-info/dependency_links.txt +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance.egg-info/requires.txt +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance.egg-info/top_level.txt +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/setup.cfg +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/setup.py +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/test/age_data.csv +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/test/cypher_queries.yaml +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/test/load_files.yaml +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/test/movies.csv +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/test/people.csv +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/test/roles.csv +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/test/test.py +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/test/test_fileload.py +0 -0
- {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/test/test_util_functions.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyneoinstance
|
|
3
|
-
Version: 4.0.
|
|
3
|
+
Version: 4.0.3
|
|
4
4
|
Summary: Handle Neo4j read and write transactions and provide methods for performing graph EDA
|
|
5
5
|
Author-email: "Jose A. Alvarado-Guzman" <jose.alvarado-guzman@neo4j.com>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -28,7 +28,11 @@ from .context import get_logger, get_batches, get_columns_diff
|
|
|
28
28
|
|
|
29
29
|
_NODE_LABEL_RE = re.compile(r"\(:?(\w*)\)")
|
|
30
30
|
_REL_TYPE_RE = re.compile(r"\[:?(\w*)\]")
|
|
31
|
-
_IMPLICIT_TX_RE = re.compile(
|
|
31
|
+
_IMPLICIT_TX_RE = re.compile(
|
|
32
|
+
r"\bIN\s+(?:\d+\s+)?CONCURRENT\s+TRANSACTIONS\b"
|
|
33
|
+
r"|\bIN\s+TRANSACTIONS\b",
|
|
34
|
+
re.IGNORECASE,
|
|
35
|
+
)
|
|
32
36
|
|
|
33
37
|
def _get_driver(neo_info : Dict[str, str]):
|
|
34
38
|
try:
|
|
@@ -197,8 +201,14 @@ class Neo4jInstance:
|
|
|
197
201
|
params = parameters or {}
|
|
198
202
|
with _get_session(self._driver, database) as session:
|
|
199
203
|
try:
|
|
200
|
-
|
|
201
|
-
|
|
204
|
+
if _IMPLICIT_TX_RE.search(query):
|
|
205
|
+
# 'CALL { ... } IN TRANSACTIONS' is only valid in an implicit
|
|
206
|
+
# (auto-commit) transaction, so it can't go through execute_read.
|
|
207
|
+
read_result = session.run(query, **params)
|
|
208
|
+
result = DataFrame(read_result.values(), columns=read_result.keys())
|
|
209
|
+
else:
|
|
210
|
+
result = session.execute_read(
|
|
211
|
+
_read_transaction_function,query=query,**params)
|
|
202
212
|
except ServiceUnavailable as exception:
|
|
203
213
|
raise ServiceUnavailable() from exception
|
|
204
214
|
except ClientError as exception:
|
|
@@ -243,8 +253,15 @@ class Neo4jInstance:
|
|
|
243
253
|
params = parameters or {}
|
|
244
254
|
with _get_session(self._driver, database) as session:
|
|
245
255
|
try:
|
|
246
|
-
|
|
247
|
-
|
|
256
|
+
if _IMPLICIT_TX_RE.search(query):
|
|
257
|
+
# 'CALL { ... } IN TRANSACTIONS' is only valid in an implicit
|
|
258
|
+
# (auto-commit) transaction, so it can't go through execute_read.
|
|
259
|
+
graph_result = session.run(query, **params)
|
|
260
|
+
list(graph_result) # consume all records so .graph() is populated
|
|
261
|
+
graph = graph_result.graph()
|
|
262
|
+
else:
|
|
263
|
+
graph = session.execute_read(
|
|
264
|
+
_graph_transaction_function, query=query, **params)
|
|
248
265
|
except ServiceUnavailable as exception:
|
|
249
266
|
raise ServiceUnavailable() from exception
|
|
250
267
|
except ClientError as exception:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyneoinstance
|
|
3
|
-
Version: 4.0.
|
|
3
|
+
Version: 4.0.3
|
|
4
4
|
Summary: Handle Neo4j read and write transactions and provide methods for performing graph EDA
|
|
5
5
|
Author-email: "Jose A. Alvarado-Guzman" <jose.alvarado-guzman@neo4j.com>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -18,9 +18,7 @@ pyneoinstance/fileload/helpers.py
|
|
|
18
18
|
pyneoinstance/fileload/loadyaml.py
|
|
19
19
|
pyneoinstance/util/__init__.py
|
|
20
20
|
pyneoinstance/util/functions.py
|
|
21
|
-
test/__init__.py
|
|
22
21
|
test/age_data.csv
|
|
23
|
-
test/context.py
|
|
24
22
|
test/cypher_queries.yaml
|
|
25
23
|
test/load_files.yaml
|
|
26
24
|
test/movies.csv
|
|
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "pyneoinstance"
|
|
9
|
-
version = "4.0.
|
|
9
|
+
version = "4.0.3"
|
|
10
10
|
description = "Handle Neo4j read and write transactions and provide methods for performing graph EDA"
|
|
11
11
|
readme = "README.md"
|
|
12
12
|
authors = [{ name = "Jose A. Alvarado-Guzman",email = "jose.alvarado-guzman@neo4j.com" }]
|
|
@@ -111,6 +111,20 @@ class TestWriteMethods(unittest.TestCase):
|
|
|
111
111
|
self.assertEqual(
|
|
112
112
|
{'nodes_created': 3, 'labels_added': 3, 'properties_set': 3}, result)
|
|
113
113
|
|
|
114
|
+
def test_execute_write_query_in_concurrent_transactions(self):
|
|
115
|
+
"""Test a query with 'CALL { ... } IN CONCURRENT TRANSACTIONS', which
|
|
116
|
+
also requires an implicit transaction rather than the managed
|
|
117
|
+
transaction used by execute_write_query for regular queries."""
|
|
118
|
+
query = """
|
|
119
|
+
UNWIND range(1, 3) AS i
|
|
120
|
+
CALL (i) {
|
|
121
|
+
CREATE (:Actor {id: i})
|
|
122
|
+
} IN 2 CONCURRENT TRANSACTIONS OF 1 ROWS
|
|
123
|
+
"""
|
|
124
|
+
result = self.graph.execute_write_query(query, self.db)
|
|
125
|
+
self.assertEqual(
|
|
126
|
+
{'nodes_created': 3, 'labels_added': 3, 'properties_set': 3}, result)
|
|
127
|
+
|
|
114
128
|
|
|
115
129
|
class TestReadAndEdaMethods(unittest.TestCase):
|
|
116
130
|
"""Test read and EDA methods. Data is loaded once for the entire class."""
|
|
@@ -173,6 +187,22 @@ class TestReadAndEdaMethods(unittest.TestCase):
|
|
|
173
187
|
query, self.db, {'movie_name': movie})
|
|
174
188
|
self.assertEqual(movie, result['movie'][0])
|
|
175
189
|
|
|
190
|
+
def test_execute_read_query_in_transactions(self):
|
|
191
|
+
"""Test a read query with 'CALL { ... } IN TRANSACTIONS', which requires
|
|
192
|
+
an implicit transaction rather than the managed transaction used by
|
|
193
|
+
execute_read_query for regular queries."""
|
|
194
|
+
plain_count = self.graph.execute_read_query(
|
|
195
|
+
"MATCH (p:Person) RETURN count(p) AS row_num", self.db)['row_num'][0]
|
|
196
|
+
query = """
|
|
197
|
+
MATCH (p:Person)
|
|
198
|
+
CALL (p) {
|
|
199
|
+
RETURN p AS person
|
|
200
|
+
} IN TRANSACTIONS OF 1000 ROWS
|
|
201
|
+
RETURN count(person) AS row_num
|
|
202
|
+
"""
|
|
203
|
+
result = self.graph.execute_read_query(query, self.db)
|
|
204
|
+
self.assertEqual(plain_count, result['row_num'][0])
|
|
205
|
+
|
|
176
206
|
def test_get_node_label_freq(self):
|
|
177
207
|
"""Test node label frequency EDA."""
|
|
178
208
|
result = self.graph.get_node_label_freq(self.db)
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"""Re-exports package modules for use by the test suite."""
|
|
2
|
-
import os
|
|
3
|
-
import sys
|
|
4
|
-
sys.path.insert(0, os.path.abspath(
|
|
5
|
-
os.path.join(os.path.dirname(__file__), '..')))
|
|
6
|
-
from pyneoinstance import fileload
|
|
7
|
-
from pyneoinstance import util
|
|
8
|
-
from pyneoinstance import database
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|