graphdatascience 1.14__tar.gz → 1.15__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.
- {graphdatascience-1.14/graphdatascience.egg-info → graphdatascience-1.15}/PKG-INFO +3 -2
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/error/cypher_warning_handler.py +6 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/graph_data_science.py +8 -1
- graphdatascience-1.15/graphdatascience/query_runner/arrow_authentication.py +18 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/arrow_graph_constructor.py +7 -2
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/arrow_query_runner.py +7 -2
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/gds_arrow_client.py +139 -41
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/neo4j_query_runner.py +29 -39
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/protocol/project_protocols.py +2 -1
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/protocol/write_protocols.py +2 -1
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/session_query_runner.py +7 -6
- graphdatascience-1.15/graphdatascience/query_runner/standalone_session_query_runner.py +76 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/termination_flag.py +3 -4
- graphdatascience-1.15/graphdatascience/retry_utils/retry_config.py +12 -0
- {graphdatascience-1.14/graphdatascience/query_runner/protocol → graphdatascience-1.15/graphdatascience/retry_utils}/retry_utils.py +5 -4
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/session/__init__.py +3 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/session/aura_api.py +65 -36
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/session/aura_api_responses.py +43 -16
- graphdatascience-1.15/graphdatascience/session/aura_api_token_authentication.py +10 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/session/aura_graph_data_science.py +37 -28
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/session/dedicated_sessions.py +80 -58
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/session/gds_sessions.py +7 -7
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/session/session_info.py +8 -4
- graphdatascience-1.15/graphdatascience/utils/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/version.py +1 -1
- {graphdatascience-1.14 → graphdatascience-1.15/graphdatascience.egg-info}/PKG-INFO +3 -2
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience.egg-info/SOURCES.txt +6 -1
- {graphdatascience-1.14 → graphdatascience-1.15}/LICENSE +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/MANIFEST.in +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/README.md +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/algo/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/algo/algo_endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/algo/algo_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/algo/single_mode_algo_endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/call_builder.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/call_parameters.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/caller_base.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/error/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/error/client_only_endpoint.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/error/endpoint_suggester.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/error/gds_not_installed.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/error/illegal_attr_checker.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/error/unable_to_connect.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/error/uncallable_namespace.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/graph/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/graph/base_graph_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/graph/graph_alpha_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/graph/graph_beta_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/graph/graph_create_result.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/graph/graph_cypher_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/graph/graph_endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/graph/graph_entity_ops_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/graph/graph_export_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/graph/graph_object.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/graph/graph_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/graph/graph_project_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/graph/graph_remote_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/graph/graph_remote_project_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/graph/graph_sample_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/graph/graph_type_check.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/graph/nx_loader.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/graph/ogb_loader.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/ignored_server_endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/model/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/model/graphsage_model.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/model/link_prediction_model.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/model/model.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/model/model_alpha_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/model/model_beta_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/model/model_endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/model/model_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/model/model_resolver.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/model/node_classification_model.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/model/node_regression_model.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/model/pipeline_model.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/model/simple_rel_embedding_model.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/pipeline/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/pipeline/classification_training_pipeline.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/pipeline/lp_pipeline_create_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/pipeline/lp_training_pipeline.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/pipeline/nc_pipeline_create_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/pipeline/nc_training_pipeline.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/pipeline/nr_pipeline_create_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/pipeline/nr_training_pipeline.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/pipeline/pipeline_alpha_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/pipeline/pipeline_beta_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/pipeline/pipeline_endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/pipeline/pipeline_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/pipeline/training_pipeline.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/py.typed +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/arrow_endpoint_version.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/arrow_info.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/cypher_graph_constructor.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/graph_constructor.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/progress/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/progress/progress_provider.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/progress/query_progress_logger.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/progress/query_progress_provider.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/progress/static_progress_provider.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/protocol/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/protocol/status.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/query_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/cora/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/cora/cora_nodes.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/cora/cora_rels.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/cora/serialize_cora.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/imdb/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/imdb/imdb_acted_in.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/imdb/imdb_actors.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/imdb/imdb_directed_in.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/imdb/imdb_directors.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/imdb/imdb_movies_with_genre.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/imdb/imdb_movies_without_genre.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/imdb/serialize_imdb.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/karate/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/karate/karate_club.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/lastfm/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/lastfm/artist_nodes.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/lastfm/serialize_lastfm.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/lastfm/user_friend_df_directed.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/lastfm/user_listen_artist_rels.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/lastfm/user_nodes.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/resources/lastfm/user_tag_artist_rels.parquet.gzip +0 -0
- {graphdatascience-1.14/graphdatascience/semantic_version → graphdatascience-1.15/graphdatascience/retry_utils}/__init__.py +0 -0
- {graphdatascience-1.14/graphdatascience/server_version → graphdatascience-1.15/graphdatascience/semantic_version}/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/semantic_version/semantic_version.py +0 -0
- {graphdatascience-1.14/graphdatascience/session/dbms → graphdatascience-1.15/graphdatascience/server_version}/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/server_version/compatible_with.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/server_version/server_version.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/session/algorithm_category.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/session/aurads_sessions.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/session/cloud_location.py +0 -0
- {graphdatascience-1.14/graphdatascience/system → graphdatascience-1.15/graphdatascience/session/dbms}/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/session/dbms/protocol_resolver.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/session/dbms/protocol_version.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/session/dbms_connection_info.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/session/region_suggester.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/session/session_sizes.py +0 -0
- {graphdatascience-1.14/graphdatascience/topological_lp → graphdatascience-1.15/graphdatascience/system}/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/system/config_endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/system/system_endpoints.py +0 -0
- {graphdatascience-1.14/graphdatascience/utils → graphdatascience-1.15/graphdatascience/topological_lp}/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/topological_lp/topological_lp_alpha_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/topological_lp/topological_lp_endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/utils/direct_util_endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/utils/util_node_property_func_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/utils/util_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/utils/util_remote_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience.egg-info/dependency_links.txt +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience.egg-info/not-zip-safe +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience.egg-info/requires.txt +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience.egg-info/top_level.txt +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/pyproject.toml +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/requirements/base/base.txt +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/requirements/base/networkx.txt +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/requirements/base/ogb.txt +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/requirements/base/rust-ext.txt +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/setup.cfg +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: graphdatascience
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.15
|
|
4
4
|
Summary: A Python client for the Neo4j Graph Data Science (GDS) library
|
|
5
5
|
Home-page: https://neo4j.com/product/graph-data-science/
|
|
6
6
|
Author: Neo4j
|
|
@@ -51,6 +51,7 @@ Dynamic: description
|
|
|
51
51
|
Dynamic: description-content-type
|
|
52
52
|
Dynamic: home-page
|
|
53
53
|
Dynamic: license
|
|
54
|
+
Dynamic: license-file
|
|
54
55
|
Dynamic: project-url
|
|
55
56
|
Dynamic: provides-extra
|
|
56
57
|
Dynamic: requires-dist
|
{graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/error/cypher_warning_handler.py
RENAMED
|
@@ -24,6 +24,12 @@ def filter_id_func_deprecation_warning() -> Callable[[F], F]:
|
|
|
24
24
|
message=r"^The query used a deprecated function. \('id' is no longer supported\)",
|
|
25
25
|
)
|
|
26
26
|
|
|
27
|
+
# since 2025.04.0
|
|
28
|
+
warnings.filterwarnings(
|
|
29
|
+
"ignore",
|
|
30
|
+
message=r"^The query used a deprecated function. \('id' has been replaced by 'elementId or an application-generated id'\)",
|
|
31
|
+
)
|
|
32
|
+
|
|
27
33
|
return func(self, *args, **kwargs)
|
|
28
34
|
|
|
29
35
|
return cast(F, wrapper)
|
|
@@ -7,6 +7,8 @@ from typing import Any, Optional, Type, Union
|
|
|
7
7
|
from neo4j import Driver
|
|
8
8
|
from pandas import DataFrame
|
|
9
9
|
|
|
10
|
+
from graphdatascience.query_runner.arrow_authentication import UsernamePasswordAuthentication
|
|
11
|
+
|
|
10
12
|
from .call_builder import IndirectCallBuilder
|
|
11
13
|
from .endpoints import AlphaEndpoints, BetaEndpoints, DirectEndpoints
|
|
12
14
|
from .error.uncallable_namespace import UncallableNamespace
|
|
@@ -93,10 +95,15 @@ class GraphDataScience(DirectEndpoints, UncallableNamespace):
|
|
|
93
95
|
|
|
94
96
|
arrow_info = ArrowInfo.create(self._query_runner)
|
|
95
97
|
if arrow and arrow_info.enabled and self._server_version >= ServerVersion(2, 1, 0):
|
|
98
|
+
arrow_auth = None
|
|
99
|
+
if auth is not None:
|
|
100
|
+
username, password = auth
|
|
101
|
+
arrow_auth = UsernamePasswordAuthentication(username, password)
|
|
102
|
+
|
|
96
103
|
self._query_runner = ArrowQueryRunner.create(
|
|
97
104
|
self._query_runner,
|
|
98
105
|
arrow_info,
|
|
99
|
-
|
|
106
|
+
arrow_auth,
|
|
100
107
|
self._query_runner.encrypted(),
|
|
101
108
|
arrow_disable_server_verification,
|
|
102
109
|
arrow_tls_root_certs,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ArrowAuthentication(ABC):
|
|
6
|
+
@abstractmethod
|
|
7
|
+
def auth_pair(self) -> tuple[str, str]:
|
|
8
|
+
"""Returns the auth pair used for authentication."""
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class UsernamePasswordAuthentication(ArrowAuthentication):
|
|
14
|
+
username: str
|
|
15
|
+
password: str
|
|
16
|
+
|
|
17
|
+
def auth_pair(self) -> tuple[str, str]:
|
|
18
|
+
return self.username, self.password
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import concurrent
|
|
4
|
+
import logging
|
|
4
5
|
import math
|
|
5
6
|
import warnings
|
|
6
7
|
from concurrent.futures import ThreadPoolExecutor
|
|
@@ -33,6 +34,7 @@ class ArrowGraphConstructor(GraphConstructor):
|
|
|
33
34
|
)
|
|
34
35
|
self._chunk_size = chunk_size
|
|
35
36
|
self._min_batch_size = chunk_size * 10
|
|
37
|
+
self._logger = logging.getLogger()
|
|
36
38
|
|
|
37
39
|
def run(self, node_dfs: list[DataFrame], relationship_dfs: list[DataFrame]) -> None:
|
|
38
40
|
try:
|
|
@@ -60,8 +62,11 @@ class ArrowGraphConstructor(GraphConstructor):
|
|
|
60
62
|
|
|
61
63
|
self._client.relationship_load_done(self._graph_name)
|
|
62
64
|
except (Exception, KeyboardInterrupt) as e:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
try:
|
|
66
|
+
self._client.abort(self._graph_name)
|
|
67
|
+
except Exception as abort_exception:
|
|
68
|
+
if "No arrow process" not in str(abort_exception):
|
|
69
|
+
self._logger.warning(f"error aborting graph creation: {abort_exception}")
|
|
65
70
|
raise e
|
|
66
71
|
|
|
67
72
|
def _partition_dfs(self, dfs: list[DataFrame]) -> list[DataFrame]:
|
{graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/arrow_query_runner.py
RENAMED
|
@@ -5,6 +5,9 @@ from typing import Any, Optional
|
|
|
5
5
|
|
|
6
6
|
from pandas import DataFrame
|
|
7
7
|
|
|
8
|
+
from graphdatascience.query_runner.arrow_authentication import ArrowAuthentication
|
|
9
|
+
from graphdatascience.retry_utils.retry_config import RetryConfig
|
|
10
|
+
|
|
8
11
|
from ..call_parameters import CallParameters
|
|
9
12
|
from ..query_runner.arrow_info import ArrowInfo
|
|
10
13
|
from ..server_version.server_version import ServerVersion
|
|
@@ -19,22 +22,24 @@ class ArrowQueryRunner(QueryRunner):
|
|
|
19
22
|
def create(
|
|
20
23
|
fallback_query_runner: QueryRunner,
|
|
21
24
|
arrow_info: ArrowInfo,
|
|
22
|
-
|
|
25
|
+
arrow_authentication: Optional[ArrowAuthentication] = None,
|
|
23
26
|
encrypted: bool = False,
|
|
24
27
|
disable_server_verification: bool = False,
|
|
25
28
|
tls_root_certs: Optional[bytes] = None,
|
|
26
29
|
connection_string_override: Optional[str] = None,
|
|
30
|
+
retry_config: Optional[RetryConfig] = None,
|
|
27
31
|
) -> ArrowQueryRunner:
|
|
28
32
|
if not arrow_info.enabled:
|
|
29
33
|
raise ValueError("Arrow is not enabled on the server")
|
|
30
34
|
|
|
31
35
|
gds_arrow_client = GdsArrowClient.create(
|
|
32
36
|
arrow_info,
|
|
33
|
-
|
|
37
|
+
arrow_authentication,
|
|
34
38
|
encrypted,
|
|
35
39
|
disable_server_verification,
|
|
36
40
|
tls_root_certs,
|
|
37
41
|
connection_string_override,
|
|
42
|
+
retry_config=retry_config,
|
|
38
43
|
)
|
|
39
44
|
|
|
40
45
|
return ArrowQueryRunner(gds_arrow_client, fallback_query_runner, fallback_query_runner.server_version())
|
{graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/gds_arrow_client.py
RENAMED
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import base64
|
|
4
4
|
import json
|
|
5
|
+
import logging
|
|
5
6
|
import re
|
|
6
7
|
import time
|
|
7
8
|
import warnings
|
|
@@ -12,11 +13,31 @@ from typing import Any, Callable, Dict, Iterable, Optional, Type, Union
|
|
|
12
13
|
import pandas
|
|
13
14
|
import pyarrow
|
|
14
15
|
from neo4j.exceptions import ClientError
|
|
15
|
-
from pyarrow import Array, ChunkedArray, DictionaryArray, RecordBatch, Table, chunked_array, flight
|
|
16
|
+
from pyarrow import Array, ChunkedArray, DictionaryArray, RecordBatch, Schema, Table, chunked_array, flight
|
|
16
17
|
from pyarrow import __version__ as arrow_version
|
|
17
|
-
from pyarrow.flight import
|
|
18
|
+
from pyarrow.flight import (
|
|
19
|
+
ClientMiddleware,
|
|
20
|
+
ClientMiddlewareFactory,
|
|
21
|
+
FlightDescriptor,
|
|
22
|
+
FlightInternalError,
|
|
23
|
+
FlightMetadataReader,
|
|
24
|
+
FlightStreamWriter,
|
|
25
|
+
FlightTimedOutError,
|
|
26
|
+
FlightUnavailableError,
|
|
27
|
+
)
|
|
18
28
|
from pyarrow.types import is_dictionary
|
|
19
|
-
from tenacity import
|
|
29
|
+
from tenacity import (
|
|
30
|
+
retry,
|
|
31
|
+
retry_any,
|
|
32
|
+
retry_if_exception_type,
|
|
33
|
+
stop_after_attempt,
|
|
34
|
+
stop_after_delay,
|
|
35
|
+
wait_exponential,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
from graphdatascience.query_runner.arrow_authentication import ArrowAuthentication, UsernamePasswordAuthentication
|
|
39
|
+
from graphdatascience.retry_utils.retry_config import RetryConfig
|
|
40
|
+
from graphdatascience.retry_utils.retry_utils import before_log
|
|
20
41
|
|
|
21
42
|
from ..semantic_version.semantic_version import SemanticVersion
|
|
22
43
|
from ..version import __version__
|
|
@@ -28,11 +49,12 @@ class GdsArrowClient:
|
|
|
28
49
|
@staticmethod
|
|
29
50
|
def create(
|
|
30
51
|
arrow_info: ArrowInfo,
|
|
31
|
-
auth: Optional[tuple[str, str]] = None,
|
|
52
|
+
auth: Optional[Union[ArrowAuthentication, tuple[str, str]]] = None,
|
|
32
53
|
encrypted: bool = False,
|
|
33
54
|
disable_server_verification: bool = False,
|
|
34
55
|
tls_root_certs: Optional[bytes] = None,
|
|
35
56
|
connection_string_override: Optional[str] = None,
|
|
57
|
+
retry_config: Optional[RetryConfig] = None,
|
|
36
58
|
) -> GdsArrowClient:
|
|
37
59
|
connection_string: str
|
|
38
60
|
if connection_string_override is not None:
|
|
@@ -44,8 +66,20 @@ class GdsArrowClient:
|
|
|
44
66
|
|
|
45
67
|
arrow_endpoint_version = ArrowEndpointVersion.from_arrow_info(arrow_info.versions)
|
|
46
68
|
|
|
69
|
+
if retry_config is None:
|
|
70
|
+
retry_config = RetryConfig(
|
|
71
|
+
retry=retry_any(
|
|
72
|
+
retry_if_exception_type(FlightTimedOutError),
|
|
73
|
+
retry_if_exception_type(FlightUnavailableError),
|
|
74
|
+
retry_if_exception_type(FlightInternalError),
|
|
75
|
+
),
|
|
76
|
+
stop=(stop_after_delay(10) | stop_after_attempt(5)),
|
|
77
|
+
wait=wait_exponential(multiplier=1, min=1, max=10),
|
|
78
|
+
)
|
|
79
|
+
|
|
47
80
|
return GdsArrowClient(
|
|
48
81
|
host,
|
|
82
|
+
retry_config,
|
|
49
83
|
int(port),
|
|
50
84
|
auth,
|
|
51
85
|
encrypted,
|
|
@@ -57,8 +91,9 @@ class GdsArrowClient:
|
|
|
57
91
|
def __init__(
|
|
58
92
|
self,
|
|
59
93
|
host: str,
|
|
94
|
+
retry_config: RetryConfig,
|
|
60
95
|
port: int = 8491,
|
|
61
|
-
auth: Optional[tuple[str, str]] = None,
|
|
96
|
+
auth: Optional[Union[ArrowAuthentication, tuple[str, str]]] = None,
|
|
62
97
|
encrypted: bool = False,
|
|
63
98
|
disable_server_verification: bool = False,
|
|
64
99
|
tls_root_certs: Optional[bytes] = None,
|
|
@@ -73,8 +108,8 @@ class GdsArrowClient:
|
|
|
73
108
|
The host address of the GDS Arrow server
|
|
74
109
|
port: int
|
|
75
110
|
The host port of the GDS Arrow server (default is 8491)
|
|
76
|
-
auth: Optional[tuple[str, str]]
|
|
77
|
-
|
|
111
|
+
auth: Optional[Union[ArrowAuthentication, tuple[str, str]]]
|
|
112
|
+
Either an implementation of ArrowAuthentication providing a pair to be used for basic authentication, or a username, password tuple
|
|
78
113
|
encrypted: bool
|
|
79
114
|
A flag that indicates whether the connection should be encrypted (default is False)
|
|
80
115
|
disable_server_verification: bool
|
|
@@ -85,17 +120,25 @@ class GdsArrowClient:
|
|
|
85
120
|
The version of the Arrow endpoint to use (default is ArrowEndpointVersion.V1)
|
|
86
121
|
user_agent: Optional[str]
|
|
87
122
|
The user agent string to use for the connection. (default is `neo4j-graphdatascience-v[VERSION] pyarrow-v[PYARROW_VERSION])
|
|
123
|
+
retry_config: Optional[RetryConfig]
|
|
124
|
+
The retry configuration to use for the Arrow requests send by the client.
|
|
88
125
|
"""
|
|
89
126
|
self._arrow_endpoint_version = arrow_endpoint_version
|
|
90
127
|
self._host = host
|
|
91
128
|
self._port = port
|
|
92
|
-
self._auth =
|
|
129
|
+
self._auth = None
|
|
93
130
|
self._encrypted = encrypted
|
|
94
131
|
self._disable_server_verification = disable_server_verification
|
|
95
132
|
self._tls_root_certs = tls_root_certs
|
|
96
133
|
self._user_agent = user_agent
|
|
134
|
+
self._retry_config = retry_config
|
|
135
|
+
self._logger = logging.getLogger("gds_arrow_client")
|
|
97
136
|
|
|
98
137
|
if auth:
|
|
138
|
+
if not isinstance(auth, ArrowAuthentication):
|
|
139
|
+
username, password = auth
|
|
140
|
+
auth = UsernamePasswordAuthentication(username, password)
|
|
141
|
+
self._auth = auth
|
|
99
142
|
self._auth_middleware = AuthMiddleware(auth)
|
|
100
143
|
|
|
101
144
|
self._flight_client = self._instantiate_flight_client()
|
|
@@ -140,9 +183,22 @@ class GdsArrowClient:
|
|
|
140
183
|
Optional[str]
|
|
141
184
|
a token from the server and returns it.
|
|
142
185
|
"""
|
|
143
|
-
|
|
186
|
+
|
|
187
|
+
@retry(
|
|
188
|
+
reraise=True,
|
|
189
|
+
before=before_log("Request token", self._logger, logging.DEBUG),
|
|
190
|
+
retry=self._retry_config.retry,
|
|
191
|
+
stop=self._retry_config.stop,
|
|
192
|
+
wait=self._retry_config.wait,
|
|
193
|
+
)
|
|
194
|
+
def auth_with_retry() -> None:
|
|
144
195
|
client = self._client()
|
|
145
|
-
|
|
196
|
+
if self._auth:
|
|
197
|
+
auth_pair = self._auth.auth_pair()
|
|
198
|
+
client.authenticate_basic_token(auth_pair[0], auth_pair[1])
|
|
199
|
+
|
|
200
|
+
if self._auth:
|
|
201
|
+
auth_with_retry()
|
|
146
202
|
return self._auth_middleware.token()
|
|
147
203
|
else:
|
|
148
204
|
return "IGNORED"
|
|
@@ -193,7 +249,7 @@ class GdsArrowClient:
|
|
|
193
249
|
if node_labels:
|
|
194
250
|
config["node_labels"] = node_labels
|
|
195
251
|
|
|
196
|
-
return self.
|
|
252
|
+
return self._do_get_with_retry(database, graph_name, proc, concurrency, config)
|
|
197
253
|
|
|
198
254
|
def get_node_labels(self, graph_name: str, database: str, concurrency: Optional[int] = None) -> pandas.DataFrame:
|
|
199
255
|
"""
|
|
@@ -213,7 +269,7 @@ class GdsArrowClient:
|
|
|
213
269
|
DataFrame
|
|
214
270
|
The requested nodes as a DataFrame
|
|
215
271
|
"""
|
|
216
|
-
return self.
|
|
272
|
+
return self._do_get_with_retry(database, graph_name, "gds.graph.nodeLabels.stream", concurrency, {})
|
|
217
273
|
|
|
218
274
|
def get_relationships(
|
|
219
275
|
self, graph_name: str, database: str, relationship_types: list[str], concurrency: Optional[int] = None
|
|
@@ -237,7 +293,7 @@ class GdsArrowClient:
|
|
|
237
293
|
DataFrame
|
|
238
294
|
The requested relationships as a DataFrame
|
|
239
295
|
"""
|
|
240
|
-
return self.
|
|
296
|
+
return self._do_get_with_retry(
|
|
241
297
|
database,
|
|
242
298
|
graph_name,
|
|
243
299
|
"gds.graph.relationships.stream",
|
|
@@ -285,7 +341,7 @@ class GdsArrowClient:
|
|
|
285
341
|
if relationship_types:
|
|
286
342
|
config["relationship_types"] = relationship_types
|
|
287
343
|
|
|
288
|
-
return self.
|
|
344
|
+
return self._do_get_with_retry(database, graph_name, proc, concurrency, config)
|
|
289
345
|
|
|
290
346
|
def create_graph(
|
|
291
347
|
self,
|
|
@@ -573,19 +629,32 @@ class GdsArrowClient:
|
|
|
573
629
|
|
|
574
630
|
def _send_action(self, action_type: str, meta_data: dict[str, Any]) -> dict[str, Any]:
|
|
575
631
|
action_type = self._versioned_action_type(action_type)
|
|
632
|
+
client = self._client()
|
|
576
633
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
634
|
+
@retry(
|
|
635
|
+
reraise=True,
|
|
636
|
+
before=before_log("Send action", self._logger, logging.DEBUG),
|
|
637
|
+
retry=self._retry_config.retry,
|
|
638
|
+
stop=self._retry_config.stop,
|
|
639
|
+
wait=self._retry_config.wait,
|
|
640
|
+
)
|
|
641
|
+
def send_with_retry() -> dict[str, Any]:
|
|
642
|
+
try:
|
|
643
|
+
result = client.do_action(
|
|
644
|
+
action=flight.Action(action_type, json.dumps(meta_data).encode("utf-8")),
|
|
645
|
+
options=flight.FlightCallOptions(timeout=20.0),
|
|
646
|
+
)
|
|
580
647
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
648
|
+
# Consume result fully to sanity check and avoid cancelled streams
|
|
649
|
+
collected_result = list(result)
|
|
650
|
+
assert len(collected_result) == 1
|
|
584
651
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
652
|
+
return json.loads(collected_result[0].body.to_pybytes().decode()) # type: ignore
|
|
653
|
+
except Exception as e:
|
|
654
|
+
self.handle_flight_error(e)
|
|
655
|
+
raise e # unreachable
|
|
656
|
+
|
|
657
|
+
return send_with_retry()
|
|
589
658
|
|
|
590
659
|
def _upload_data(
|
|
591
660
|
self,
|
|
@@ -605,17 +674,26 @@ class GdsArrowClient:
|
|
|
605
674
|
flight_descriptor = self._versioned_flight_descriptor({"name": graph_name, "entity_type": entity_type})
|
|
606
675
|
upload_descriptor = flight.FlightDescriptor.for_command(json.dumps(flight_descriptor).encode("utf-8"))
|
|
607
676
|
|
|
608
|
-
|
|
609
|
-
|
|
677
|
+
@retry(
|
|
678
|
+
reraise=True,
|
|
679
|
+
before=before_log("Do put", self._logger, logging.DEBUG),
|
|
680
|
+
retry=self._retry_config.retry,
|
|
681
|
+
stop=self._retry_config.stop,
|
|
682
|
+
wait=self._retry_config.wait,
|
|
683
|
+
)
|
|
684
|
+
def safe_do_put(
|
|
685
|
+
upload_descriptor: FlightDescriptor, schema: Schema
|
|
686
|
+
) -> tuple[FlightStreamWriter, FlightMetadataReader]:
|
|
687
|
+
return self._client().do_put(upload_descriptor, schema) # type: ignore
|
|
688
|
+
|
|
689
|
+
put_stream, ack_stream = safe_do_put(upload_descriptor, batches[0].schema)
|
|
610
690
|
|
|
611
691
|
@retry(
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
retry=
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
| retry_if_exception_type(flight.FlightInternalError)
|
|
618
|
-
),
|
|
692
|
+
reraise=True,
|
|
693
|
+
before=before_log("Upload batch", self._logger, logging.DEBUG),
|
|
694
|
+
retry=self._retry_config.retry,
|
|
695
|
+
stop=self._retry_config.stop,
|
|
696
|
+
wait=self._retry_config.wait,
|
|
619
697
|
)
|
|
620
698
|
def upload_batch(p: RecordBatch) -> None:
|
|
621
699
|
put_stream.write_batch(p)
|
|
@@ -629,6 +707,26 @@ class GdsArrowClient:
|
|
|
629
707
|
except Exception as e:
|
|
630
708
|
GdsArrowClient.handle_flight_error(e)
|
|
631
709
|
|
|
710
|
+
def _do_get_with_retry(
|
|
711
|
+
self,
|
|
712
|
+
database: str,
|
|
713
|
+
graph_name: str,
|
|
714
|
+
procedure_name: str,
|
|
715
|
+
concurrency: Optional[int],
|
|
716
|
+
configuration: dict[str, Any],
|
|
717
|
+
) -> pandas.DataFrame:
|
|
718
|
+
@retry(
|
|
719
|
+
reraise=True,
|
|
720
|
+
before=before_log("Do get", self._logger, logging.DEBUG),
|
|
721
|
+
retry=self._retry_config.retry,
|
|
722
|
+
stop=self._retry_config.stop,
|
|
723
|
+
wait=self._retry_config.wait,
|
|
724
|
+
)
|
|
725
|
+
def safe_do_get() -> pandas.DataFrame:
|
|
726
|
+
return self._do_get(database, graph_name, procedure_name, concurrency, configuration)
|
|
727
|
+
|
|
728
|
+
return safe_do_get()
|
|
729
|
+
|
|
632
730
|
def _do_get(
|
|
633
731
|
self,
|
|
634
732
|
database: str,
|
|
@@ -795,7 +893,7 @@ class AuthFactory(ClientMiddlewareFactory): # type: ignore
|
|
|
795
893
|
|
|
796
894
|
|
|
797
895
|
class AuthMiddleware(ClientMiddleware): # type: ignore
|
|
798
|
-
def __init__(self, auth:
|
|
896
|
+
def __init__(self, auth: ArrowAuthentication, *args: Any, **kwargs: Any) -> None:
|
|
799
897
|
super().__init__(*args, **kwargs)
|
|
800
898
|
self._auth = auth
|
|
801
899
|
self._token: Optional[str] = None
|
|
@@ -829,15 +927,15 @@ class AuthMiddleware(ClientMiddleware): # type: ignore
|
|
|
829
927
|
|
|
830
928
|
def sending_headers(self) -> dict[str, str]:
|
|
831
929
|
token = self.token()
|
|
832
|
-
if not
|
|
833
|
-
username, password = self._auth
|
|
834
|
-
auth_token = f"{username}:{password}"
|
|
835
|
-
auth_token = "Basic " + base64.b64encode(auth_token.encode("utf-8")).decode("ASCII")
|
|
836
|
-
# There seems to be a bug, `authorization` must be lower key
|
|
837
|
-
return {"authorization": auth_token}
|
|
838
|
-
else:
|
|
930
|
+
if token is not None:
|
|
839
931
|
return {"authorization": "Bearer " + token}
|
|
840
932
|
|
|
933
|
+
auth_pair = self._auth.auth_pair()
|
|
934
|
+
auth_token = f"{auth_pair[0]}:{auth_pair[1]}"
|
|
935
|
+
auth_token = "Basic " + base64.b64encode(auth_token.encode("utf-8")).decode("ASCII")
|
|
936
|
+
# There seems to be a bug, `authorization` must be lower key
|
|
937
|
+
return {"authorization": auth_token}
|
|
938
|
+
|
|
841
939
|
|
|
842
940
|
@dataclass(repr=True, frozen=True)
|
|
843
941
|
class NodeLoadDoneResult:
|
{graphdatascience-1.14 → graphdatascience-1.15}/graphdatascience/query_runner/neo4j_query_runner.py
RENAMED
|
@@ -57,19 +57,9 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
57
57
|
query_runner = Neo4jQueryRunner(
|
|
58
58
|
endpoint, auto_close=False, bookmarks=bookmarks, database=database, show_progress=show_progress
|
|
59
59
|
)
|
|
60
|
-
|
|
61
60
|
else:
|
|
62
61
|
raise ValueError(f"Invalid endpoint type: {type(endpoint)}")
|
|
63
62
|
|
|
64
|
-
if Neo4jQueryRunner._NEO4J_DRIVER_VERSION >= SemanticVersion(5, 21, 0):
|
|
65
|
-
notifications_logger = logging.getLogger("neo4j.notifications")
|
|
66
|
-
# the client does not expose YIELD fields so we just skip these warnings for now
|
|
67
|
-
notifications_logger.addFilter(
|
|
68
|
-
lambda record: (
|
|
69
|
-
"The query used a deprecated field from a procedure" in record.msg and "by 'gds." in record.msg
|
|
70
|
-
)
|
|
71
|
-
)
|
|
72
|
-
|
|
73
63
|
return query_runner
|
|
74
64
|
|
|
75
65
|
@staticmethod
|
|
@@ -90,19 +80,12 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
90
80
|
show_progress=show_progress,
|
|
91
81
|
bookmarks=None,
|
|
92
82
|
config=driver_config,
|
|
83
|
+
# we need to explicitly set this as the default value is None
|
|
84
|
+
# database in the session is always neo4j
|
|
93
85
|
database="neo4j",
|
|
94
86
|
instance_description="GDS Session",
|
|
95
87
|
)
|
|
96
88
|
|
|
97
|
-
if Neo4jQueryRunner._NEO4J_DRIVER_VERSION >= SemanticVersion(5, 21, 0):
|
|
98
|
-
notifications_logger = logging.getLogger("neo4j.notifications")
|
|
99
|
-
# the client does not expose YIELD fields so we just skip these warnings for now
|
|
100
|
-
notifications_logger.addFilter(
|
|
101
|
-
lambda record: (
|
|
102
|
-
"The query used a deprecated field from a procedure" in record.msg and "by 'gds." in record.msg
|
|
103
|
-
)
|
|
104
|
-
)
|
|
105
|
-
|
|
106
89
|
return query_runner
|
|
107
90
|
|
|
108
91
|
@staticmethod
|
|
@@ -167,12 +150,7 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
167
150
|
else:
|
|
168
151
|
raise e
|
|
169
152
|
|
|
170
|
-
|
|
171
|
-
# be supported in the `graphdatascience` package.
|
|
172
|
-
warnings.filterwarnings(
|
|
173
|
-
"ignore",
|
|
174
|
-
message=r"^pandas support is experimental and might be changed or removed in future versions$",
|
|
175
|
-
)
|
|
153
|
+
self.__configure_warnings_filter()
|
|
176
154
|
|
|
177
155
|
df = result.to_df()
|
|
178
156
|
|
|
@@ -181,19 +159,10 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
181
159
|
else:
|
|
182
160
|
self._last_bookmarks = session.last_bookmarks()
|
|
183
161
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
# the client does not expose YIELD fields so we just skip these warnings for now
|
|
189
|
-
warnings.filterwarnings(
|
|
190
|
-
"ignore", message=r".*The query used a deprecated field from a procedure\. .* by 'gds.* "
|
|
191
|
-
)
|
|
192
|
-
else:
|
|
193
|
-
notifications = result.consume().notifications
|
|
194
|
-
if notifications:
|
|
195
|
-
for notification in notifications:
|
|
196
|
-
self._forward_cypher_warnings(notification)
|
|
162
|
+
notifications = result.consume().notifications
|
|
163
|
+
if notifications:
|
|
164
|
+
for notification in notifications:
|
|
165
|
+
self._forward_cypher_warnings(notification)
|
|
197
166
|
|
|
198
167
|
return df
|
|
199
168
|
|
|
@@ -266,7 +235,7 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
266
235
|
# (see https://neo4j.com/docs/status-codes/current/notifications/ for more details)
|
|
267
236
|
severity = notification["severity"]
|
|
268
237
|
if severity == "WARNING":
|
|
269
|
-
if "
|
|
238
|
+
if "deprecated field" in notification["description"] and "procedure" in notification["description"]:
|
|
270
239
|
# the client does not expose YIELD fields so we just skip these warnings for now
|
|
271
240
|
return
|
|
272
241
|
|
|
@@ -373,6 +342,27 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
373
342
|
if retrys == retry_config.max_retries:
|
|
374
343
|
raise UnableToConnectError(f"Unable to connect to the {self._instance_description}") from exception
|
|
375
344
|
|
|
345
|
+
def __configure_warnings_filter(self) -> None:
|
|
346
|
+
if Neo4jQueryRunner._NEO4J_DRIVER_VERSION >= SemanticVersion(5, 21, 0):
|
|
347
|
+
notifications_logger = logging.getLogger("neo4j.notifications")
|
|
348
|
+
# the client does not expose YIELD fields so we just skip these warnings for now
|
|
349
|
+
notifications_logger.addFilter(
|
|
350
|
+
lambda record: (
|
|
351
|
+
"The query used a deprecated field from a procedure" in record.msg and "by 'gds." in record.msg
|
|
352
|
+
)
|
|
353
|
+
)
|
|
354
|
+
notifications_logger.addFilter(
|
|
355
|
+
lambda record: "The procedure has a deprecated field" in record.msg and "gds." in record.msg
|
|
356
|
+
)
|
|
357
|
+
warnings.filterwarnings(
|
|
358
|
+
"ignore",
|
|
359
|
+
message=r"^pandas support is experimental and might be changed or removed in future versions$",
|
|
360
|
+
)
|
|
361
|
+
# neo4j 2025.04
|
|
362
|
+
warnings.filterwarnings("ignore", message=r".*The procedure has a deprecated field.*by 'gds.*")
|
|
363
|
+
# neo4j driver 4.4
|
|
364
|
+
warnings.filterwarnings("ignore", message=r".*The query used a deprecated field from a procedure.*by 'gds.*")
|
|
365
|
+
|
|
376
366
|
class ConnectivityRetriesConfig(NamedTuple):
|
|
377
367
|
max_retries: int = 600
|
|
378
368
|
wait_time: int = 1
|
|
@@ -7,9 +7,9 @@ from tenacity import retry, retry_if_result, wait_incrementing
|
|
|
7
7
|
|
|
8
8
|
from graphdatascience import QueryRunner
|
|
9
9
|
from graphdatascience.call_parameters import CallParameters
|
|
10
|
-
from graphdatascience.query_runner.protocol.retry_utils import before_log
|
|
11
10
|
from graphdatascience.query_runner.protocol.status import Status
|
|
12
11
|
from graphdatascience.query_runner.termination_flag import TerminationFlag
|
|
12
|
+
from graphdatascience.retry_utils.retry_utils import before_log
|
|
13
13
|
from graphdatascience.session.dbms.protocol_version import ProtocolVersion
|
|
14
14
|
|
|
15
15
|
|
|
@@ -133,6 +133,7 @@ class ProjectProtocolV3(ProjectProtocol):
|
|
|
133
133
|
logger = getLogger()
|
|
134
134
|
|
|
135
135
|
@retry(
|
|
136
|
+
reraise=True,
|
|
136
137
|
before=before_log(f"Projection (graph: `{params['graph_name']}`)", logger, DEBUG),
|
|
137
138
|
retry=retry_if_result(is_not_done),
|
|
138
139
|
wait=wait_incrementing(start=0.2, increment=0.2, max=2),
|
|
@@ -7,9 +7,9 @@ from tenacity import retry, retry_if_result, wait_incrementing
|
|
|
7
7
|
|
|
8
8
|
from graphdatascience import QueryRunner
|
|
9
9
|
from graphdatascience.call_parameters import CallParameters
|
|
10
|
-
from graphdatascience.query_runner.protocol.retry_utils import before_log
|
|
11
10
|
from graphdatascience.query_runner.protocol.status import Status
|
|
12
11
|
from graphdatascience.query_runner.termination_flag import TerminationFlag
|
|
12
|
+
from graphdatascience.retry_utils.retry_utils import before_log
|
|
13
13
|
from graphdatascience.session.dbms.protocol_version import ProtocolVersion
|
|
14
14
|
|
|
15
15
|
|
|
@@ -142,6 +142,7 @@ class RemoteWriteBackV3(WriteProtocol):
|
|
|
142
142
|
logger = logging.getLogger()
|
|
143
143
|
|
|
144
144
|
@retry(
|
|
145
|
+
reraise=True,
|
|
145
146
|
retry=retry_if_result(is_not_completed),
|
|
146
147
|
wait=wait_incrementing(start=0.2, increment=0.2, max=2),
|
|
147
148
|
before=before_log(
|
|
@@ -202,12 +202,13 @@ class SessionQueryRunner(QueryRunner):
|
|
|
202
202
|
return write_protocol.run_write_back(self._db_query_runner, write_back_params, yields, terminationFlag)
|
|
203
203
|
|
|
204
204
|
try:
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
205
|
+
# Skipping progress for now as export has a different jobId
|
|
206
|
+
# if self._resolve_show_progress(logging):
|
|
207
|
+
# database_write_result = self._progress_logger.run_with_progress_logging(
|
|
208
|
+
# run_write_back, job_id, database
|
|
209
|
+
# )
|
|
210
|
+
# else:
|
|
211
|
+
database_write_result = run_write_back()
|
|
211
212
|
except Exception as e:
|
|
212
213
|
# catch the case nothing was needed to write-back (empty graph)
|
|
213
214
|
# once we have the Arrow Endpoints V2, we could catch by first checking the jobs summary
|