biocypher 0.5.40__tar.gz → 0.5.41__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.
Potentially problematic release.
This version of biocypher might be problematic. Click here for more details.
- {biocypher-0.5.40 → biocypher-0.5.41}/PKG-INFO +1 -1
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/_connect.py +36 -9
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/_metadata.py +1 -1
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/_misc.py +6 -2
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/write/_write.py +1 -1
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/write/graph/_neo4j.py +44 -3
- {biocypher-0.5.40 → biocypher-0.5.41}/pyproject.toml +1 -1
- {biocypher-0.5.40 → biocypher-0.5.41}/LICENSE +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/README.md +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/__init__.py +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/_config/__init__.py +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/_config/biocypher_config.yaml +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/_config/test_config.yaml +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/_config/test_schema_config.yaml +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/_config/test_schema_config_disconnected.yaml +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/_config/test_schema_config_extended.yaml +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/_core.py +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/_create.py +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/_deduplicate.py +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/_get.py +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/_logger.py +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/_mapping.py +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/_ontology.py +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/_pandas.py +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/_translate.py +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/write/__init__.py +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/write/_batch_writer.py +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/write/graph/__init__.py +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/write/graph/_arangodb.py +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/write/relational/__init__.py +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/write/relational/_postgresql.py +0 -0
- {biocypher-0.5.40 → biocypher-0.5.41}/biocypher/write/relational/_sqlite.py +0 -0
|
@@ -11,11 +11,12 @@
|
|
|
11
11
|
"""
|
|
12
12
|
BioCypher 'online' mode. Handles connection and manipulation of a running DBMS.
|
|
13
13
|
"""
|
|
14
|
+
import subprocess
|
|
15
|
+
|
|
14
16
|
from ._logger import logger
|
|
15
17
|
|
|
16
18
|
logger.debug(f"Loading module {__name__}.")
|
|
17
19
|
|
|
18
|
-
from typing import Optional
|
|
19
20
|
from collections.abc import Iterable
|
|
20
21
|
import itertools
|
|
21
22
|
|
|
@@ -24,7 +25,6 @@ import neo4j_utils
|
|
|
24
25
|
from . import _misc
|
|
25
26
|
from ._config import config as _config
|
|
26
27
|
from ._create import BioCypherEdge, BioCypherNode
|
|
27
|
-
from ._ontology import Ontology
|
|
28
28
|
from ._translate import Translator
|
|
29
29
|
|
|
30
30
|
__all__ = ["_Neo4jDriver"]
|
|
@@ -137,16 +137,43 @@ class _Neo4jDriver:
|
|
|
137
137
|
|
|
138
138
|
logger.info("Creating constraints for node types in config.")
|
|
139
139
|
|
|
140
|
+
major_neo4j_version = int(self._get_neo4j_version().split(".")[0])
|
|
140
141
|
# get structure
|
|
141
142
|
for leaf in self.translator.ontology.mapping.extended_schema.items():
|
|
142
|
-
label = _misc.sentencecase_to_pascalcase(leaf[0])
|
|
143
|
+
label = _misc.sentencecase_to_pascalcase(leaf[0], sep=r"\s\.")
|
|
143
144
|
if leaf[1]["represented_as"] == "node":
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
145
|
+
if major_neo4j_version >= 5:
|
|
146
|
+
s = (
|
|
147
|
+
f"CREATE CONSTRAINT `{label}_id` "
|
|
148
|
+
f"IF NOT EXISTS FOR (n:`{label}`) "
|
|
149
|
+
"REQUIRE n.id IS UNIQUE"
|
|
150
|
+
)
|
|
151
|
+
self._driver.query(s)
|
|
152
|
+
else:
|
|
153
|
+
s = (
|
|
154
|
+
f"CREATE CONSTRAINT `{label}_id` "
|
|
155
|
+
f"IF NOT EXISTS ON (n:`{label}`) "
|
|
156
|
+
"ASSERT n.id IS UNIQUE"
|
|
157
|
+
)
|
|
158
|
+
self._driver.query(s)
|
|
159
|
+
|
|
160
|
+
def _get_neo4j_version(self):
|
|
161
|
+
"""Get neo4j version."""
|
|
162
|
+
try:
|
|
163
|
+
neo4j_version = self._driver.query(
|
|
164
|
+
"""
|
|
165
|
+
CALL dbms.components()
|
|
166
|
+
YIELD name, versions, edition
|
|
167
|
+
UNWIND versions AS version
|
|
168
|
+
RETURN version AS version
|
|
169
|
+
""",
|
|
170
|
+
)[0][0]["version"]
|
|
171
|
+
return neo4j_version
|
|
172
|
+
except Exception as e:
|
|
173
|
+
logger.warning(
|
|
174
|
+
f"Error detecting Neo4j version: {e} use default version 4.0.0."
|
|
175
|
+
)
|
|
176
|
+
return "4.0.0"
|
|
150
177
|
|
|
151
178
|
def add_nodes(self, id_type_tuples: Iterable[tuple]) -> tuple:
|
|
152
179
|
"""
|
|
@@ -205,7 +205,7 @@ def sentencecase_to_snakecase(s: str) -> str:
|
|
|
205
205
|
return stringcase.snakecase(s).lower()
|
|
206
206
|
|
|
207
207
|
|
|
208
|
-
def sentencecase_to_pascalcase(s: str) -> str:
|
|
208
|
+
def sentencecase_to_pascalcase(s: str, sep: str = r"\s") -> str:
|
|
209
209
|
"""
|
|
210
210
|
Convert sentence case to PascalCase.
|
|
211
211
|
|
|
@@ -215,7 +215,11 @@ def sentencecase_to_pascalcase(s: str) -> str:
|
|
|
215
215
|
Returns:
|
|
216
216
|
string in PascalCase form
|
|
217
217
|
"""
|
|
218
|
-
return re.sub(
|
|
218
|
+
return re.sub(
|
|
219
|
+
r"(?:^|[" + sep + "])([a-zA-Z])",
|
|
220
|
+
lambda match: match.group(1).upper(),
|
|
221
|
+
s,
|
|
222
|
+
)
|
|
219
223
|
|
|
220
224
|
|
|
221
225
|
def to_lower_sentence_case(s: str) -> str:
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import re
|
|
3
|
+
import subprocess
|
|
2
4
|
|
|
3
5
|
from biocypher._logger import logger
|
|
4
6
|
from biocypher.write._batch_writer import parse_label, _BatchWriter
|
|
@@ -22,6 +24,19 @@ class _Neo4jBatchWriter(_BatchWriter):
|
|
|
22
24
|
- _write_array_string
|
|
23
25
|
"""
|
|
24
26
|
|
|
27
|
+
def __init__(self, *args, **kwargs):
|
|
28
|
+
"""
|
|
29
|
+
Constructor.
|
|
30
|
+
|
|
31
|
+
Check the version of Neo4j and adds a command scope if version >= 5.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
_Neo4jBatchWriter: An instance of the writer.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
# Should read the configuration and setup import_call_bin_prefix.
|
|
38
|
+
super().__init__(*args, **kwargs)
|
|
39
|
+
|
|
25
40
|
def _get_default_import_call_bin_prefix(self):
|
|
26
41
|
"""
|
|
27
42
|
Method to provide the default string for the import call bin prefix.
|
|
@@ -29,6 +44,7 @@ class _Neo4jBatchWriter(_BatchWriter):
|
|
|
29
44
|
Returns:
|
|
30
45
|
str: The default location for the neo4j admin import location
|
|
31
46
|
"""
|
|
47
|
+
|
|
32
48
|
return "bin/"
|
|
33
49
|
|
|
34
50
|
def _write_array_string(self, string_list):
|
|
@@ -263,9 +279,32 @@ class _Neo4jBatchWriter(_BatchWriter):
|
|
|
263
279
|
Returns:
|
|
264
280
|
str: a bash command for neo4j-admin import
|
|
265
281
|
"""
|
|
282
|
+
import_call_neo4j_v4 = self._get_import_call(
|
|
283
|
+
"import", "--database=", "--force="
|
|
284
|
+
)
|
|
285
|
+
import_call_neo4j_v5 = self._get_import_call(
|
|
286
|
+
"database import full", "", "--overwrite-destination="
|
|
287
|
+
)
|
|
288
|
+
neo4j_version_check = f"version=$({self._get_default_import_call_bin_prefix()}neo4j-admin --version | cut -d '.' -f 1)"
|
|
289
|
+
|
|
290
|
+
import_script = f"#!/bin/bash\n{neo4j_version_check}\nif [[ $version -ge 5 ]]; then\n\t{import_call_neo4j_v5}\nelse\n\t{import_call_neo4j_v4}\nfi"
|
|
291
|
+
return import_script
|
|
292
|
+
|
|
293
|
+
def _get_import_call(
|
|
294
|
+
self, import_cmd: str, database_cmd: str, wipe_cmd: str
|
|
295
|
+
) -> str:
|
|
296
|
+
"""Get parametrized import call for Neo4j 4 or 5+.
|
|
297
|
+
|
|
298
|
+
Args:
|
|
299
|
+
import_cmd (str): The import command to use.
|
|
300
|
+
database_cmd (str): The database command to use.
|
|
301
|
+
wipe_cmd (str): The wipe command to use.
|
|
302
|
+
|
|
303
|
+
Returns:
|
|
304
|
+
str: The import call.
|
|
305
|
+
"""
|
|
266
306
|
import_call = (
|
|
267
|
-
f"{self.import_call_bin_prefix}neo4j-admin
|
|
268
|
-
f"--database={self.db_name} "
|
|
307
|
+
f"{self.import_call_bin_prefix}neo4j-admin {import_cmd} "
|
|
269
308
|
f'--delimiter="{self.escaped_delim}" '
|
|
270
309
|
f'--array-delimiter="{self.escaped_adelim}" '
|
|
271
310
|
)
|
|
@@ -276,7 +315,7 @@ class _Neo4jBatchWriter(_BatchWriter):
|
|
|
276
315
|
import_call += f"--quote='{self.quote}' "
|
|
277
316
|
|
|
278
317
|
if self.wipe:
|
|
279
|
-
import_call += f"
|
|
318
|
+
import_call += f"{wipe_cmd}true "
|
|
280
319
|
if self.skip_bad_relationships:
|
|
281
320
|
import_call += "--skip-bad-relationships=true "
|
|
282
321
|
if self.skip_duplicate_nodes:
|
|
@@ -290,4 +329,6 @@ class _Neo4jBatchWriter(_BatchWriter):
|
|
|
290
329
|
for header_path, parts_path in self.import_call_edges:
|
|
291
330
|
import_call += f'--relationships="{header_path},{parts_path}" '
|
|
292
331
|
|
|
332
|
+
# Database needs to be at the end starting with Neo4j 5.0+.
|
|
333
|
+
import_call += f"{database_cmd}{self.db_name} "
|
|
293
334
|
return import_call
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{biocypher-0.5.40 → biocypher-0.5.41}/biocypher/_config/test_schema_config_disconnected.yaml
RENAMED
|
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
|