graphdatascience 1.14__tar.gz → 1.15a2__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.15a2}/PKG-INFO +3 -2
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/error/cypher_warning_handler.py +6 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/graph_data_science.py +8 -1
- graphdatascience-1.15a2/graphdatascience/query_runner/arrow_authentication.py +18 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/arrow_query_runner.py +7 -2
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/gds_arrow_client.py +136 -41
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/neo4j_query_runner.py +29 -39
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/protocol/project_protocols.py +2 -1
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/protocol/write_protocols.py +2 -1
- graphdatascience-1.15a2/graphdatascience/query_runner/standalone_session_query_runner.py +76 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/termination_flag.py +3 -4
- graphdatascience-1.15a2/graphdatascience/retry_utils/retry_config.py +12 -0
- {graphdatascience-1.14/graphdatascience/query_runner/protocol → graphdatascience-1.15a2/graphdatascience/retry_utils}/retry_utils.py +5 -4
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/session/__init__.py +3 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/session/aura_api.py +64 -35
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/session/aura_api_responses.py +43 -16
- graphdatascience-1.15a2/graphdatascience/session/aura_api_token_authentication.py +10 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/session/aura_graph_data_science.py +37 -28
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/session/dedicated_sessions.py +80 -58
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/session/gds_sessions.py +7 -7
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/session/session_info.py +8 -4
- graphdatascience-1.15a2/graphdatascience/utils/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/version.py +1 -1
- {graphdatascience-1.14 → graphdatascience-1.15a2/graphdatascience.egg-info}/PKG-INFO +3 -2
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience.egg-info/SOURCES.txt +6 -1
- {graphdatascience-1.14 → graphdatascience-1.15a2}/LICENSE +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/MANIFEST.in +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/README.md +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/algo/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/algo/algo_endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/algo/algo_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/algo/single_mode_algo_endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/call_builder.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/call_parameters.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/caller_base.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/error/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/error/client_only_endpoint.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/error/endpoint_suggester.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/error/gds_not_installed.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/error/illegal_attr_checker.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/error/unable_to_connect.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/error/uncallable_namespace.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/graph/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/graph/base_graph_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/graph/graph_alpha_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/graph/graph_beta_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/graph/graph_create_result.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/graph/graph_cypher_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/graph/graph_endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/graph/graph_entity_ops_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/graph/graph_export_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/graph/graph_object.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/graph/graph_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/graph/graph_project_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/graph/graph_remote_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/graph/graph_remote_project_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/graph/graph_sample_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/graph/graph_type_check.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/graph/nx_loader.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/graph/ogb_loader.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/ignored_server_endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/model/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/model/graphsage_model.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/model/link_prediction_model.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/model/model.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/model/model_alpha_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/model/model_beta_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/model/model_endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/model/model_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/model/model_resolver.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/model/node_classification_model.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/model/node_regression_model.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/model/pipeline_model.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/model/simple_rel_embedding_model.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/pipeline/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/pipeline/classification_training_pipeline.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/pipeline/lp_pipeline_create_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/pipeline/lp_training_pipeline.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/pipeline/nc_pipeline_create_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/pipeline/nc_training_pipeline.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/pipeline/nr_pipeline_create_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/pipeline/nr_training_pipeline.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/pipeline/pipeline_alpha_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/pipeline/pipeline_beta_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/pipeline/pipeline_endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/pipeline/pipeline_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/pipeline/training_pipeline.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/py.typed +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/arrow_endpoint_version.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/arrow_graph_constructor.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/arrow_info.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/cypher_graph_constructor.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/graph_constructor.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/progress/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/progress/progress_provider.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/progress/query_progress_logger.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/progress/query_progress_provider.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/progress/static_progress_provider.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/protocol/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/protocol/status.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/query_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/query_runner/session_query_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/cora/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/cora/cora_nodes.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/cora/cora_rels.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/cora/serialize_cora.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/imdb/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/imdb/imdb_acted_in.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/imdb/imdb_actors.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/imdb/imdb_directed_in.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/imdb/imdb_directors.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/imdb/imdb_movies_with_genre.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/imdb/imdb_movies_without_genre.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/imdb/serialize_imdb.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/karate/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/karate/karate_club.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/lastfm/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/lastfm/artist_nodes.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/lastfm/serialize_lastfm.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/lastfm/user_friend_df_directed.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/lastfm/user_listen_artist_rels.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/lastfm/user_nodes.parquet.gzip +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/resources/lastfm/user_tag_artist_rels.parquet.gzip +0 -0
- {graphdatascience-1.14/graphdatascience/semantic_version → graphdatascience-1.15a2/graphdatascience/retry_utils}/__init__.py +0 -0
- {graphdatascience-1.14/graphdatascience/server_version → graphdatascience-1.15a2/graphdatascience/semantic_version}/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/semantic_version/semantic_version.py +0 -0
- {graphdatascience-1.14/graphdatascience/session/dbms → graphdatascience-1.15a2/graphdatascience/server_version}/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/server_version/compatible_with.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/server_version/server_version.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/session/algorithm_category.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/session/aurads_sessions.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/session/cloud_location.py +0 -0
- {graphdatascience-1.14/graphdatascience/system → graphdatascience-1.15a2/graphdatascience/session/dbms}/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/session/dbms/protocol_resolver.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/session/dbms/protocol_version.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/session/dbms_connection_info.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/session/region_suggester.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/session/session_sizes.py +0 -0
- {graphdatascience-1.14/graphdatascience/topological_lp → graphdatascience-1.15a2/graphdatascience/system}/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/system/config_endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/system/system_endpoints.py +0 -0
- {graphdatascience-1.14/graphdatascience/utils → graphdatascience-1.15a2/graphdatascience/topological_lp}/__init__.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/topological_lp/topological_lp_alpha_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/topological_lp/topological_lp_endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/utils/direct_util_endpoints.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/utils/util_node_property_func_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/utils/util_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience/utils/util_remote_proc_runner.py +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience.egg-info/dependency_links.txt +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience.egg-info/not-zip-safe +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience.egg-info/requires.txt +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/graphdatascience.egg-info/top_level.txt +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/pyproject.toml +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/requirements/base/base.txt +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/requirements/base/networkx.txt +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/requirements/base/ogb.txt +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/requirements/base/rust-ext.txt +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/setup.cfg +0 -0
- {graphdatascience-1.14 → graphdatascience-1.15a2}/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.15a2
|
|
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.15a2}/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
|
|
@@ -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.15a2}/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,29 @@ 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(flight.Action(action_type, json.dumps(meta_data).encode("utf-8")))
|
|
580
644
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
645
|
+
# Consume result fully to sanity check and avoid cancelled streams
|
|
646
|
+
collected_result = list(result)
|
|
647
|
+
assert len(collected_result) == 1
|
|
584
648
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
649
|
+
return json.loads(collected_result[0].body.to_pybytes().decode()) # type: ignore
|
|
650
|
+
except Exception as e:
|
|
651
|
+
self.handle_flight_error(e)
|
|
652
|
+
raise e # unreachable
|
|
653
|
+
|
|
654
|
+
return send_with_retry()
|
|
589
655
|
|
|
590
656
|
def _upload_data(
|
|
591
657
|
self,
|
|
@@ -605,17 +671,26 @@ class GdsArrowClient:
|
|
|
605
671
|
flight_descriptor = self._versioned_flight_descriptor({"name": graph_name, "entity_type": entity_type})
|
|
606
672
|
upload_descriptor = flight.FlightDescriptor.for_command(json.dumps(flight_descriptor).encode("utf-8"))
|
|
607
673
|
|
|
608
|
-
|
|
609
|
-
|
|
674
|
+
@retry(
|
|
675
|
+
reraise=True,
|
|
676
|
+
before=before_log("Do put", self._logger, logging.DEBUG),
|
|
677
|
+
retry=self._retry_config.retry,
|
|
678
|
+
stop=self._retry_config.stop,
|
|
679
|
+
wait=self._retry_config.wait,
|
|
680
|
+
)
|
|
681
|
+
def safe_do_put(
|
|
682
|
+
upload_descriptor: FlightDescriptor, schema: Schema
|
|
683
|
+
) -> tuple[FlightStreamWriter, FlightMetadataReader]:
|
|
684
|
+
return self._client().do_put(upload_descriptor, schema) # type: ignore
|
|
685
|
+
|
|
686
|
+
put_stream, ack_stream = safe_do_put(upload_descriptor, batches[0].schema)
|
|
610
687
|
|
|
611
688
|
@retry(
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
retry=
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
| retry_if_exception_type(flight.FlightInternalError)
|
|
618
|
-
),
|
|
689
|
+
reraise=True,
|
|
690
|
+
before=before_log("Upload batch", self._logger, logging.DEBUG),
|
|
691
|
+
retry=self._retry_config.retry,
|
|
692
|
+
stop=self._retry_config.stop,
|
|
693
|
+
wait=self._retry_config.wait,
|
|
619
694
|
)
|
|
620
695
|
def upload_batch(p: RecordBatch) -> None:
|
|
621
696
|
put_stream.write_batch(p)
|
|
@@ -629,6 +704,26 @@ class GdsArrowClient:
|
|
|
629
704
|
except Exception as e:
|
|
630
705
|
GdsArrowClient.handle_flight_error(e)
|
|
631
706
|
|
|
707
|
+
def _do_get_with_retry(
|
|
708
|
+
self,
|
|
709
|
+
database: str,
|
|
710
|
+
graph_name: str,
|
|
711
|
+
procedure_name: str,
|
|
712
|
+
concurrency: Optional[int],
|
|
713
|
+
configuration: dict[str, Any],
|
|
714
|
+
) -> pandas.DataFrame:
|
|
715
|
+
@retry(
|
|
716
|
+
reraise=True,
|
|
717
|
+
before=before_log("Do get", self._logger, logging.DEBUG),
|
|
718
|
+
retry=self._retry_config.retry,
|
|
719
|
+
stop=self._retry_config.stop,
|
|
720
|
+
wait=self._retry_config.wait,
|
|
721
|
+
)
|
|
722
|
+
def safe_do_get() -> pandas.DataFrame:
|
|
723
|
+
return self._do_get(database, graph_name, procedure_name, concurrency, configuration)
|
|
724
|
+
|
|
725
|
+
return safe_do_get()
|
|
726
|
+
|
|
632
727
|
def _do_get(
|
|
633
728
|
self,
|
|
634
729
|
database: str,
|
|
@@ -795,7 +890,7 @@ class AuthFactory(ClientMiddlewareFactory): # type: ignore
|
|
|
795
890
|
|
|
796
891
|
|
|
797
892
|
class AuthMiddleware(ClientMiddleware): # type: ignore
|
|
798
|
-
def __init__(self, auth:
|
|
893
|
+
def __init__(self, auth: ArrowAuthentication, *args: Any, **kwargs: Any) -> None:
|
|
799
894
|
super().__init__(*args, **kwargs)
|
|
800
895
|
self._auth = auth
|
|
801
896
|
self._token: Optional[str] = None
|
|
@@ -829,15 +924,15 @@ class AuthMiddleware(ClientMiddleware): # type: ignore
|
|
|
829
924
|
|
|
830
925
|
def sending_headers(self) -> dict[str, str]:
|
|
831
926
|
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:
|
|
927
|
+
if token is not None:
|
|
839
928
|
return {"authorization": "Bearer " + token}
|
|
840
929
|
|
|
930
|
+
auth_pair = self._auth.auth_pair()
|
|
931
|
+
auth_token = f"{auth_pair[0]}:{auth_pair[1]}"
|
|
932
|
+
auth_token = "Basic " + base64.b64encode(auth_token.encode("utf-8")).decode("ASCII")
|
|
933
|
+
# There seems to be a bug, `authorization` must be lower key
|
|
934
|
+
return {"authorization": auth_token}
|
|
935
|
+
|
|
841
936
|
|
|
842
937
|
@dataclass(repr=True, frozen=True)
|
|
843
938
|
class NodeLoadDoneResult:
|
|
@@ -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(
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from typing import Any, Optional
|
|
2
|
+
|
|
3
|
+
from pandas import DataFrame
|
|
4
|
+
|
|
5
|
+
from graphdatascience import QueryRunner, ServerVersion
|
|
6
|
+
from graphdatascience.call_parameters import CallParameters
|
|
7
|
+
from graphdatascience.query_runner.graph_constructor import GraphConstructor
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class StandaloneSessionQueryRunner(QueryRunner):
|
|
11
|
+
def __init__(self, session_query_runner: QueryRunner):
|
|
12
|
+
self._query_runner = session_query_runner
|
|
13
|
+
|
|
14
|
+
def call_procedure(
|
|
15
|
+
self,
|
|
16
|
+
endpoint: str,
|
|
17
|
+
params: Optional[CallParameters] = None,
|
|
18
|
+
yields: Optional[list[str]] = None,
|
|
19
|
+
database: Optional[str] = None,
|
|
20
|
+
logging: bool = False,
|
|
21
|
+
custom_error: bool = True,
|
|
22
|
+
) -> DataFrame:
|
|
23
|
+
if endpoint.endswith(".write"):
|
|
24
|
+
raise NotImplementedError("write procedures are not supported on standalone sessions")
|
|
25
|
+
|
|
26
|
+
return self._query_runner.call_procedure(endpoint, params, yields, database, logging, custom_error)
|
|
27
|
+
|
|
28
|
+
def call_function(self, endpoint: str, params: Optional[CallParameters] = None) -> Any:
|
|
29
|
+
return self._query_runner.call_function(endpoint, params)
|
|
30
|
+
|
|
31
|
+
def server_version(self) -> ServerVersion:
|
|
32
|
+
return self._query_runner.server_version()
|
|
33
|
+
|
|
34
|
+
def create_graph_constructor(
|
|
35
|
+
self, graph_name: str, concurrency: int, undirected_relationship_types: Optional[list[str]]
|
|
36
|
+
) -> GraphConstructor:
|
|
37
|
+
return self._query_runner.create_graph_constructor(graph_name, concurrency, undirected_relationship_types)
|
|
38
|
+
|
|
39
|
+
def set_show_progress(self, show_progress: bool) -> None:
|
|
40
|
+
self._query_runner.set_show_progress(show_progress)
|
|
41
|
+
|
|
42
|
+
def encrypted(self) -> bool:
|
|
43
|
+
return self._query_runner.encrypted()
|
|
44
|
+
|
|
45
|
+
def close(self) -> None:
|
|
46
|
+
self._query_runner.close()
|
|
47
|
+
|
|
48
|
+
def database(self) -> Optional[str]:
|
|
49
|
+
return "neo4j"
|
|
50
|
+
|
|
51
|
+
def run_cypher(
|
|
52
|
+
self,
|
|
53
|
+
query: str,
|
|
54
|
+
params: Optional[dict[str, Any]] = None,
|
|
55
|
+
database: Optional[str] = None,
|
|
56
|
+
custom_error: bool = True,
|
|
57
|
+
) -> DataFrame:
|
|
58
|
+
raise NotImplementedError
|
|
59
|
+
|
|
60
|
+
def driver_config(self) -> dict[str, Any]:
|
|
61
|
+
raise NotImplementedError
|
|
62
|
+
|
|
63
|
+
def set_database(self, database: str) -> None:
|
|
64
|
+
raise NotImplementedError
|
|
65
|
+
|
|
66
|
+
def set_bookmarks(self, bookmarks: Optional[Any]) -> None:
|
|
67
|
+
raise NotImplementedError
|
|
68
|
+
|
|
69
|
+
def bookmarks(self) -> Optional[Any]:
|
|
70
|
+
raise NotImplementedError
|
|
71
|
+
|
|
72
|
+
def last_bookmarks(self) -> Optional[Any]:
|
|
73
|
+
raise NotImplementedError
|
|
74
|
+
|
|
75
|
+
def set_server_version(self, _: ServerVersion) -> None:
|
|
76
|
+
super().set_server_version(_)
|