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.
Files changed (34) hide show
  1. {pyneoinstance-4.0.2/pyneoinstance.egg-info → pyneoinstance-4.0.3}/PKG-INFO +1 -1
  2. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/__init__.py +1 -1
  3. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/database/neo4jdbms.py +22 -5
  4. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3/pyneoinstance.egg-info}/PKG-INFO +1 -1
  5. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance.egg-info/SOURCES.txt +0 -2
  6. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyproject.toml +1 -1
  7. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/test/test_neo4jdb.py +30 -0
  8. pyneoinstance-4.0.2/test/__init__.py +0 -3
  9. pyneoinstance-4.0.2/test/context.py +0 -8
  10. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/LICENSE +0 -0
  11. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/MANIFEST.in +0 -0
  12. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/README.md +0 -0
  13. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/database/__init__.py +0 -0
  14. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/database/context.py +0 -0
  15. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/fileload/__init__.py +0 -0
  16. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/fileload/helpers.py +0 -0
  17. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/fileload/loadyaml.py +0 -0
  18. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/py.typed +0 -0
  19. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/util/__init__.py +0 -0
  20. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance/util/functions.py +0 -0
  21. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance.egg-info/dependency_links.txt +0 -0
  22. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance.egg-info/requires.txt +0 -0
  23. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/pyneoinstance.egg-info/top_level.txt +0 -0
  24. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/setup.cfg +0 -0
  25. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/setup.py +0 -0
  26. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/test/age_data.csv +0 -0
  27. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/test/cypher_queries.yaml +0 -0
  28. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/test/load_files.yaml +0 -0
  29. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/test/movies.csv +0 -0
  30. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/test/people.csv +0 -0
  31. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/test/roles.csv +0 -0
  32. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/test/test.py +0 -0
  33. {pyneoinstance-4.0.2 → pyneoinstance-4.0.3}/test/test_fileload.py +0 -0
  34. {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.2
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
@@ -1,5 +1,5 @@
1
1
  from .database.neo4jdbms import Neo4jInstance
2
2
  from .fileload.loadyaml import load_yaml_file
3
3
 
4
- __version__ = '4.0.2'
4
+ __version__ = '4.0.3'
5
5
  __all__ = ['Neo4jInstance', 'load_yaml_file']
@@ -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(r"\bIN\s+TRANSACTIONS\b", re.IGNORECASE)
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
- result = session.execute_read(
201
- _read_transaction_function,query=query,**params)
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
- graph = session.execute_read(
247
- _graph_transaction_function, query=query, **params)
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.2
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.2"
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,3 +0,0 @@
1
- import os
2
-
3
- test_dir = os.path.abspath(os.path.dirname(__file__))
@@ -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