graphdatascience 1.15a1__tar.gz → 1.15.1__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.15a1/graphdatascience.egg-info → graphdatascience-1.15.1}/PKG-INFO +1 -1
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/error/cypher_warning_handler.py +6 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/graph_data_science.py +8 -1
- graphdatascience-1.15.1/graphdatascience/query_runner/arrow_authentication.py +18 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/arrow_graph_constructor.py +7 -2
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/arrow_query_runner.py +10 -2
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/gds_arrow_client.py +24 -15
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/neo4j_query_runner.py +67 -40
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/protocol/project_protocols.py +16 -4
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/query_runner.py +4 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/session_query_runner.py +15 -6
- graphdatascience-1.15.1/graphdatascience/query_runner/standalone_session_query_runner.py +81 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/session/__init__.py +3 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/session/aura_api.py +62 -41
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/session/aura_api_responses.py +43 -16
- graphdatascience-1.15.1/graphdatascience/session/aura_api_token_authentication.py +10 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/session/aura_graph_data_science.py +37 -28
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/session/dedicated_sessions.py +78 -50
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/session/gds_sessions.py +7 -7
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/session/session_info.py +8 -4
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/session/session_sizes.py +1 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/version.py +1 -1
- {graphdatascience-1.15a1 → graphdatascience-1.15.1/graphdatascience.egg-info}/PKG-INFO +1 -1
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience.egg-info/SOURCES.txt +3 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/LICENSE +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/MANIFEST.in +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/README.md +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/algo/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/algo/algo_endpoints.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/algo/algo_proc_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/algo/single_mode_algo_endpoints.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/call_builder.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/call_parameters.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/caller_base.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/endpoints.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/error/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/error/client_only_endpoint.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/error/endpoint_suggester.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/error/gds_not_installed.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/error/illegal_attr_checker.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/error/unable_to_connect.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/error/uncallable_namespace.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/graph/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/graph/base_graph_proc_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/graph/graph_alpha_proc_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/graph/graph_beta_proc_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/graph/graph_create_result.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/graph/graph_cypher_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/graph/graph_endpoints.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/graph/graph_entity_ops_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/graph/graph_export_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/graph/graph_object.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/graph/graph_proc_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/graph/graph_project_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/graph/graph_remote_proc_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/graph/graph_remote_project_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/graph/graph_sample_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/graph/graph_type_check.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/graph/nx_loader.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/graph/ogb_loader.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/ignored_server_endpoints.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/model/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/model/graphsage_model.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/model/link_prediction_model.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/model/model.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/model/model_alpha_proc_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/model/model_beta_proc_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/model/model_endpoints.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/model/model_proc_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/model/model_resolver.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/model/node_classification_model.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/model/node_regression_model.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/model/pipeline_model.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/model/simple_rel_embedding_model.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/pipeline/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/pipeline/classification_training_pipeline.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/pipeline/lp_pipeline_create_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/pipeline/lp_training_pipeline.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/pipeline/nc_pipeline_create_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/pipeline/nc_training_pipeline.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/pipeline/nr_pipeline_create_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/pipeline/nr_training_pipeline.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/pipeline/pipeline_alpha_proc_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/pipeline/pipeline_beta_proc_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/pipeline/pipeline_endpoints.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/pipeline/pipeline_proc_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/pipeline/training_pipeline.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/py.typed +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/arrow_endpoint_version.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/arrow_info.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/cypher_graph_constructor.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/graph_constructor.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/progress/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/progress/progress_provider.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/progress/query_progress_logger.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/progress/query_progress_provider.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/progress/static_progress_provider.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/protocol/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/protocol/status.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/protocol/write_protocols.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/query_runner/termination_flag.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/cora/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/cora/cora_nodes.parquet.gzip +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/cora/cora_rels.parquet.gzip +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/cora/serialize_cora.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/imdb/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/imdb/imdb_acted_in.parquet.gzip +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/imdb/imdb_actors.parquet.gzip +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/imdb/imdb_directed_in.parquet.gzip +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/imdb/imdb_directors.parquet.gzip +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/imdb/imdb_movies_with_genre.parquet.gzip +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/imdb/imdb_movies_without_genre.parquet.gzip +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/imdb/serialize_imdb.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/karate/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/karate/karate_club.parquet.gzip +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/lastfm/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/lastfm/artist_nodes.parquet.gzip +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/lastfm/serialize_lastfm.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/lastfm/user_friend_df_directed.parquet.gzip +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/lastfm/user_listen_artist_rels.parquet.gzip +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/lastfm/user_nodes.parquet.gzip +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/resources/lastfm/user_tag_artist_rels.parquet.gzip +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/retry_utils/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/retry_utils/retry_config.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/retry_utils/retry_utils.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/semantic_version/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/semantic_version/semantic_version.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/server_version/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/server_version/compatible_with.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/server_version/server_version.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/session/algorithm_category.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/session/aurads_sessions.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/session/cloud_location.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/session/dbms/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/session/dbms/protocol_resolver.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/session/dbms/protocol_version.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/session/dbms_connection_info.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/session/region_suggester.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/system/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/system/config_endpoints.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/system/system_endpoints.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/topological_lp/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/topological_lp/topological_lp_alpha_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/topological_lp/topological_lp_endpoints.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/utils/__init__.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/utils/direct_util_endpoints.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/utils/util_node_property_func_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/utils/util_proc_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience/utils/util_remote_proc_runner.py +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience.egg-info/dependency_links.txt +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience.egg-info/not-zip-safe +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience.egg-info/requires.txt +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/graphdatascience.egg-info/top_level.txt +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/pyproject.toml +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/requirements/base/base.txt +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/requirements/base/networkx.txt +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/requirements/base/ogb.txt +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/requirements/base/rust-ext.txt +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/setup.cfg +0 -0
- {graphdatascience-1.15a1 → graphdatascience-1.15.1}/setup.py +0 -0
{graphdatascience-1.15a1 → graphdatascience-1.15.1}/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]:
|
|
@@ -5,6 +5,7 @@ from typing import Any, Optional
|
|
|
5
5
|
|
|
6
6
|
from pandas import DataFrame
|
|
7
7
|
|
|
8
|
+
from graphdatascience.query_runner.arrow_authentication import ArrowAuthentication
|
|
8
9
|
from graphdatascience.retry_utils.retry_config import RetryConfig
|
|
9
10
|
|
|
10
11
|
from ..call_parameters import CallParameters
|
|
@@ -21,7 +22,7 @@ class ArrowQueryRunner(QueryRunner):
|
|
|
21
22
|
def create(
|
|
22
23
|
fallback_query_runner: QueryRunner,
|
|
23
24
|
arrow_info: ArrowInfo,
|
|
24
|
-
|
|
25
|
+
arrow_authentication: Optional[ArrowAuthentication] = None,
|
|
25
26
|
encrypted: bool = False,
|
|
26
27
|
disable_server_verification: bool = False,
|
|
27
28
|
tls_root_certs: Optional[bytes] = None,
|
|
@@ -33,7 +34,7 @@ class ArrowQueryRunner(QueryRunner):
|
|
|
33
34
|
|
|
34
35
|
gds_arrow_client = GdsArrowClient.create(
|
|
35
36
|
arrow_info,
|
|
36
|
-
|
|
37
|
+
arrow_authentication,
|
|
37
38
|
encrypted,
|
|
38
39
|
disable_server_verification,
|
|
39
40
|
tls_root_certs,
|
|
@@ -210,6 +211,13 @@ class ArrowQueryRunner(QueryRunner):
|
|
|
210
211
|
self._fallback_query_runner.close()
|
|
211
212
|
self._gds_arrow_client.close()
|
|
212
213
|
|
|
214
|
+
def clone(self, host: str, port: int) -> "QueryRunner":
|
|
215
|
+
return ArrowQueryRunner(
|
|
216
|
+
self._gds_arrow_client,
|
|
217
|
+
self._fallback_query_runner.clone(host, port),
|
|
218
|
+
self._server_version,
|
|
219
|
+
)
|
|
220
|
+
|
|
213
221
|
def fallback_query_runner(self) -> QueryRunner:
|
|
214
222
|
return self._fallback_query_runner
|
|
215
223
|
|
|
@@ -35,6 +35,7 @@ from tenacity import (
|
|
|
35
35
|
wait_exponential,
|
|
36
36
|
)
|
|
37
37
|
|
|
38
|
+
from graphdatascience.query_runner.arrow_authentication import ArrowAuthentication, UsernamePasswordAuthentication
|
|
38
39
|
from graphdatascience.retry_utils.retry_config import RetryConfig
|
|
39
40
|
from graphdatascience.retry_utils.retry_utils import before_log
|
|
40
41
|
|
|
@@ -48,7 +49,7 @@ class GdsArrowClient:
|
|
|
48
49
|
@staticmethod
|
|
49
50
|
def create(
|
|
50
51
|
arrow_info: ArrowInfo,
|
|
51
|
-
auth: Optional[tuple[str, str]] = None,
|
|
52
|
+
auth: Optional[Union[ArrowAuthentication, tuple[str, str]]] = None,
|
|
52
53
|
encrypted: bool = False,
|
|
53
54
|
disable_server_verification: bool = False,
|
|
54
55
|
tls_root_certs: Optional[bytes] = None,
|
|
@@ -92,7 +93,7 @@ class GdsArrowClient:
|
|
|
92
93
|
host: str,
|
|
93
94
|
retry_config: RetryConfig,
|
|
94
95
|
port: int = 8491,
|
|
95
|
-
auth: Optional[tuple[str, str]] = None,
|
|
96
|
+
auth: Optional[Union[ArrowAuthentication, tuple[str, str]]] = None,
|
|
96
97
|
encrypted: bool = False,
|
|
97
98
|
disable_server_verification: bool = False,
|
|
98
99
|
tls_root_certs: Optional[bytes] = None,
|
|
@@ -107,8 +108,8 @@ class GdsArrowClient:
|
|
|
107
108
|
The host address of the GDS Arrow server
|
|
108
109
|
port: int
|
|
109
110
|
The host port of the GDS Arrow server (default is 8491)
|
|
110
|
-
auth: Optional[tuple[str, str]]
|
|
111
|
-
|
|
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
|
|
112
113
|
encrypted: bool
|
|
113
114
|
A flag that indicates whether the connection should be encrypted (default is False)
|
|
114
115
|
disable_server_verification: bool
|
|
@@ -125,7 +126,7 @@ class GdsArrowClient:
|
|
|
125
126
|
self._arrow_endpoint_version = arrow_endpoint_version
|
|
126
127
|
self._host = host
|
|
127
128
|
self._port = port
|
|
128
|
-
self._auth =
|
|
129
|
+
self._auth = None
|
|
129
130
|
self._encrypted = encrypted
|
|
130
131
|
self._disable_server_verification = disable_server_verification
|
|
131
132
|
self._tls_root_certs = tls_root_certs
|
|
@@ -134,6 +135,10 @@ class GdsArrowClient:
|
|
|
134
135
|
self._logger = logging.getLogger("gds_arrow_client")
|
|
135
136
|
|
|
136
137
|
if auth:
|
|
138
|
+
if not isinstance(auth, ArrowAuthentication):
|
|
139
|
+
username, password = auth
|
|
140
|
+
auth = UsernamePasswordAuthentication(username, password)
|
|
141
|
+
self._auth = auth
|
|
137
142
|
self._auth_middleware = AuthMiddleware(auth)
|
|
138
143
|
|
|
139
144
|
self._flight_client = self._instantiate_flight_client()
|
|
@@ -189,7 +194,8 @@ class GdsArrowClient:
|
|
|
189
194
|
def auth_with_retry() -> None:
|
|
190
195
|
client = self._client()
|
|
191
196
|
if self._auth:
|
|
192
|
-
|
|
197
|
+
auth_pair = self._auth.auth_pair()
|
|
198
|
+
client.authenticate_basic_token(auth_pair[0], auth_pair[1])
|
|
193
199
|
|
|
194
200
|
if self._auth:
|
|
195
201
|
auth_with_retry()
|
|
@@ -634,7 +640,10 @@ class GdsArrowClient:
|
|
|
634
640
|
)
|
|
635
641
|
def send_with_retry() -> dict[str, Any]:
|
|
636
642
|
try:
|
|
637
|
-
result = client.do_action(
|
|
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
|
+
)
|
|
638
647
|
|
|
639
648
|
# Consume result fully to sanity check and avoid cancelled streams
|
|
640
649
|
collected_result = list(result)
|
|
@@ -884,7 +893,7 @@ class AuthFactory(ClientMiddlewareFactory): # type: ignore
|
|
|
884
893
|
|
|
885
894
|
|
|
886
895
|
class AuthMiddleware(ClientMiddleware): # type: ignore
|
|
887
|
-
def __init__(self, auth:
|
|
896
|
+
def __init__(self, auth: ArrowAuthentication, *args: Any, **kwargs: Any) -> None:
|
|
888
897
|
super().__init__(*args, **kwargs)
|
|
889
898
|
self._auth = auth
|
|
890
899
|
self._token: Optional[str] = None
|
|
@@ -918,15 +927,15 @@ class AuthMiddleware(ClientMiddleware): # type: ignore
|
|
|
918
927
|
|
|
919
928
|
def sending_headers(self) -> dict[str, str]:
|
|
920
929
|
token = self.token()
|
|
921
|
-
if not
|
|
922
|
-
username, password = self._auth
|
|
923
|
-
auth_token = f"{username}:{password}"
|
|
924
|
-
auth_token = "Basic " + base64.b64encode(auth_token.encode("utf-8")).decode("ASCII")
|
|
925
|
-
# There seems to be a bug, `authorization` must be lower key
|
|
926
|
-
return {"authorization": auth_token}
|
|
927
|
-
else:
|
|
930
|
+
if token is not None:
|
|
928
931
|
return {"authorization": "Bearer " + token}
|
|
929
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
|
+
|
|
930
939
|
|
|
931
940
|
@dataclass(repr=True, frozen=True)
|
|
932
941
|
class NodeLoadDoneResult:
|
|
@@ -46,6 +46,8 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
46
46
|
|
|
47
47
|
query_runner = Neo4jQueryRunner(
|
|
48
48
|
driver,
|
|
49
|
+
Neo4jQueryRunner.parse_protocol(endpoint),
|
|
50
|
+
auth,
|
|
49
51
|
auto_close=True,
|
|
50
52
|
bookmarks=bookmarks,
|
|
51
53
|
config=config,
|
|
@@ -54,22 +56,18 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
54
56
|
)
|
|
55
57
|
|
|
56
58
|
elif isinstance(endpoint, neo4j.Driver):
|
|
59
|
+
protocol = "neo4j+s" if endpoint.encrypted else "bolt"
|
|
57
60
|
query_runner = Neo4jQueryRunner(
|
|
58
|
-
endpoint,
|
|
61
|
+
endpoint,
|
|
62
|
+
protocol,
|
|
63
|
+
auto_close=False,
|
|
64
|
+
bookmarks=bookmarks,
|
|
65
|
+
database=database,
|
|
66
|
+
show_progress=show_progress,
|
|
59
67
|
)
|
|
60
|
-
|
|
61
68
|
else:
|
|
62
69
|
raise ValueError(f"Invalid endpoint type: {type(endpoint)}")
|
|
63
70
|
|
|
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
71
|
return query_runner
|
|
74
72
|
|
|
75
73
|
@staticmethod
|
|
@@ -86,23 +84,18 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
86
84
|
|
|
87
85
|
query_runner = Neo4jQueryRunner(
|
|
88
86
|
driver,
|
|
87
|
+
Neo4jQueryRunner.parse_protocol(endpoint),
|
|
88
|
+
auth,
|
|
89
89
|
auto_close=True,
|
|
90
90
|
show_progress=show_progress,
|
|
91
91
|
bookmarks=None,
|
|
92
92
|
config=driver_config,
|
|
93
|
+
# we need to explicitly set this as the default value is None
|
|
94
|
+
# database in the session is always neo4j
|
|
93
95
|
database="neo4j",
|
|
94
96
|
instance_description="GDS Session",
|
|
95
97
|
)
|
|
96
98
|
|
|
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
99
|
return query_runner
|
|
107
100
|
|
|
108
101
|
@staticmethod
|
|
@@ -111,9 +104,18 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
111
104
|
config["keep_alive"] = True
|
|
112
105
|
config["max_connection_pool_size"] = 50
|
|
113
106
|
|
|
107
|
+
@staticmethod
|
|
108
|
+
def parse_protocol(endpoint: str) -> str:
|
|
109
|
+
protocol_match = re.match(r"^([^:]+)://", endpoint)
|
|
110
|
+
if not protocol_match:
|
|
111
|
+
raise ValueError(f"Invalid endpoint URI format: {endpoint}")
|
|
112
|
+
return protocol_match.group(1)
|
|
113
|
+
|
|
114
114
|
def __init__(
|
|
115
115
|
self,
|
|
116
116
|
driver: neo4j.Driver,
|
|
117
|
+
protocol: str,
|
|
118
|
+
auth: Optional[tuple[str, str]] = None,
|
|
117
119
|
config: dict[str, Any] = {},
|
|
118
120
|
database: Optional[str] = neo4j.DEFAULT_DATABASE,
|
|
119
121
|
auto_close: bool = False,
|
|
@@ -122,6 +124,8 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
122
124
|
instance_description: str = "Neo4j DBMS",
|
|
123
125
|
):
|
|
124
126
|
self._driver = driver
|
|
127
|
+
self._protocol = protocol
|
|
128
|
+
self._auth = auth
|
|
125
129
|
self._config = config
|
|
126
130
|
self._auto_close = auto_close
|
|
127
131
|
self._database = database
|
|
@@ -167,12 +171,7 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
167
171
|
else:
|
|
168
172
|
raise e
|
|
169
173
|
|
|
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
|
-
)
|
|
174
|
+
self.__configure_warnings_filter()
|
|
176
175
|
|
|
177
176
|
df = result.to_df()
|
|
178
177
|
|
|
@@ -181,19 +180,10 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
181
180
|
else:
|
|
182
181
|
self._last_bookmarks = session.last_bookmarks()
|
|
183
182
|
|
|
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)
|
|
183
|
+
notifications = result.consume().notifications
|
|
184
|
+
if notifications:
|
|
185
|
+
for notification in notifications:
|
|
186
|
+
self._forward_cypher_warnings(notification)
|
|
197
187
|
|
|
198
188
|
return df
|
|
199
189
|
|
|
@@ -266,7 +256,7 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
266
256
|
# (see https://neo4j.com/docs/status-codes/current/notifications/ for more details)
|
|
267
257
|
severity = notification["severity"]
|
|
268
258
|
if severity == "WARNING":
|
|
269
|
-
if "
|
|
259
|
+
if "deprecated field" in notification["description"] and "procedure" in notification["description"]:
|
|
270
260
|
# the client does not expose YIELD fields so we just skip these warnings for now
|
|
271
261
|
return
|
|
272
262
|
|
|
@@ -310,6 +300,22 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
310
300
|
def set_show_progress(self, show_progress: bool) -> None:
|
|
311
301
|
self._show_progress = show_progress
|
|
312
302
|
|
|
303
|
+
def clone(self, host: str, port: int) -> QueryRunner:
|
|
304
|
+
endpoint = "{}://{}:{}".format(self._protocol, host, port)
|
|
305
|
+
driver = neo4j.GraphDatabase.driver(endpoint, auth=self._auth, **self.driver_config())
|
|
306
|
+
|
|
307
|
+
return Neo4jQueryRunner(
|
|
308
|
+
driver,
|
|
309
|
+
self._protocol,
|
|
310
|
+
self._auth,
|
|
311
|
+
self._config,
|
|
312
|
+
self._database,
|
|
313
|
+
self._auto_close,
|
|
314
|
+
self._bookmarks,
|
|
315
|
+
self._show_progress,
|
|
316
|
+
self._instance_description,
|
|
317
|
+
)
|
|
318
|
+
|
|
313
319
|
@staticmethod
|
|
314
320
|
def handle_driver_exception(session: neo4j.Session, e: Exception) -> None:
|
|
315
321
|
reg_gds_hit = re.search(
|
|
@@ -373,6 +379,27 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
373
379
|
if retrys == retry_config.max_retries:
|
|
374
380
|
raise UnableToConnectError(f"Unable to connect to the {self._instance_description}") from exception
|
|
375
381
|
|
|
382
|
+
def __configure_warnings_filter(self) -> None:
|
|
383
|
+
if Neo4jQueryRunner._NEO4J_DRIVER_VERSION >= SemanticVersion(5, 21, 0):
|
|
384
|
+
notifications_logger = logging.getLogger("neo4j.notifications")
|
|
385
|
+
# the client does not expose YIELD fields so we just skip these warnings for now
|
|
386
|
+
notifications_logger.addFilter(
|
|
387
|
+
lambda record: (
|
|
388
|
+
"The query used a deprecated field from a procedure" in record.msg and "by 'gds." in record.msg
|
|
389
|
+
)
|
|
390
|
+
)
|
|
391
|
+
notifications_logger.addFilter(
|
|
392
|
+
lambda record: "The procedure has a deprecated field" in record.msg and "gds." in record.msg
|
|
393
|
+
)
|
|
394
|
+
warnings.filterwarnings(
|
|
395
|
+
"ignore",
|
|
396
|
+
message=r"^pandas support is experimental and might be changed or removed in future versions$",
|
|
397
|
+
)
|
|
398
|
+
# neo4j 2025.04
|
|
399
|
+
warnings.filterwarnings("ignore", message=r".*The procedure has a deprecated field.*by 'gds.*")
|
|
400
|
+
# neo4j driver 4.4
|
|
401
|
+
warnings.filterwarnings("ignore", message=r".*The query used a deprecated field from a procedure.*by 'gds.*")
|
|
402
|
+
|
|
376
403
|
class ConnectivityRetriesConfig(NamedTuple):
|
|
377
404
|
max_retries: int = 600
|
|
378
405
|
wait_time: int = 1
|
|
@@ -121,7 +121,7 @@ class ProjectProtocolV3(ProjectProtocol):
|
|
|
121
121
|
query_runner: QueryRunner,
|
|
122
122
|
endpoint: str,
|
|
123
123
|
params: CallParameters,
|
|
124
|
-
|
|
124
|
+
termination_flag: TerminationFlag,
|
|
125
125
|
yields: Optional[list[str]] = None,
|
|
126
126
|
database: Optional[str] = None,
|
|
127
127
|
logging: bool = False,
|
|
@@ -132,6 +132,14 @@ class ProjectProtocolV3(ProjectProtocol):
|
|
|
132
132
|
|
|
133
133
|
logger = getLogger()
|
|
134
134
|
|
|
135
|
+
# We need to pin the driver to a specific cluster member
|
|
136
|
+
response = query_runner.call_procedure(
|
|
137
|
+
ProtocolVersion.V3.versioned_procedure_name(endpoint), params, yields, database, logging, False
|
|
138
|
+
).squeeze()
|
|
139
|
+
member_host = response["host"]
|
|
140
|
+
member_port = response["port"] if ("port" in response.index) else 7687
|
|
141
|
+
projection_query_runner = query_runner.clone(member_host, member_port)
|
|
142
|
+
|
|
135
143
|
@retry(
|
|
136
144
|
reraise=True,
|
|
137
145
|
before=before_log(f"Projection (graph: `{params['graph_name']}`)", logger, DEBUG),
|
|
@@ -139,9 +147,13 @@ class ProjectProtocolV3(ProjectProtocol):
|
|
|
139
147
|
wait=wait_incrementing(start=0.2, increment=0.2, max=2),
|
|
140
148
|
)
|
|
141
149
|
def project_fn() -> DataFrame:
|
|
142
|
-
|
|
143
|
-
return
|
|
150
|
+
termination_flag.assert_running()
|
|
151
|
+
return projection_query_runner.call_procedure(
|
|
144
152
|
ProtocolVersion.V3.versioned_procedure_name(endpoint), params, yields, database, logging, False
|
|
145
153
|
)
|
|
146
154
|
|
|
147
|
-
|
|
155
|
+
projection_result = project_fn()
|
|
156
|
+
|
|
157
|
+
projection_query_runner.close()
|
|
158
|
+
|
|
159
|
+
return projection_result
|
|
@@ -120,6 +120,14 @@ class SessionQueryRunner(QueryRunner):
|
|
|
120
120
|
self._show_progress = show_progress
|
|
121
121
|
self._gds_query_runner.set_show_progress(show_progress)
|
|
122
122
|
|
|
123
|
+
def clone(self, host: str, port: int) -> QueryRunner:
|
|
124
|
+
return SessionQueryRunner(
|
|
125
|
+
self._gds_query_runner,
|
|
126
|
+
self._db_query_runner.clone(host, port),
|
|
127
|
+
self._gds_arrow_client,
|
|
128
|
+
self._show_progress,
|
|
129
|
+
)
|
|
130
|
+
|
|
123
131
|
def close(self) -> None:
|
|
124
132
|
self._gds_arrow_client.close()
|
|
125
133
|
self._gds_query_runner.close()
|
|
@@ -202,12 +210,13 @@ class SessionQueryRunner(QueryRunner):
|
|
|
202
210
|
return write_protocol.run_write_back(self._db_query_runner, write_back_params, yields, terminationFlag)
|
|
203
211
|
|
|
204
212
|
try:
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
213
|
+
# Skipping progress for now as export has a different jobId
|
|
214
|
+
# if self._resolve_show_progress(logging):
|
|
215
|
+
# database_write_result = self._progress_logger.run_with_progress_logging(
|
|
216
|
+
# run_write_back, job_id, database
|
|
217
|
+
# )
|
|
218
|
+
# else:
|
|
219
|
+
database_write_result = run_write_back()
|
|
211
220
|
except Exception as e:
|
|
212
221
|
# catch the case nothing was needed to write-back (empty graph)
|
|
213
222
|
# once we have the Arrow Endpoints V2, we could catch by first checking the jobs summary
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, Optional
|
|
4
|
+
|
|
5
|
+
from pandas import DataFrame
|
|
6
|
+
|
|
7
|
+
from graphdatascience import QueryRunner, ServerVersion
|
|
8
|
+
from graphdatascience.call_parameters import CallParameters
|
|
9
|
+
from graphdatascience.query_runner.graph_constructor import GraphConstructor
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class StandaloneSessionQueryRunner(QueryRunner):
|
|
13
|
+
def __init__(self, session_query_runner: QueryRunner):
|
|
14
|
+
self._query_runner = session_query_runner
|
|
15
|
+
|
|
16
|
+
def call_procedure(
|
|
17
|
+
self,
|
|
18
|
+
endpoint: str,
|
|
19
|
+
params: Optional[CallParameters] = None,
|
|
20
|
+
yields: Optional[list[str]] = None,
|
|
21
|
+
database: Optional[str] = None,
|
|
22
|
+
logging: bool = False,
|
|
23
|
+
custom_error: bool = True,
|
|
24
|
+
) -> DataFrame:
|
|
25
|
+
if endpoint.endswith(".write"):
|
|
26
|
+
raise NotImplementedError("write procedures are not supported on standalone sessions")
|
|
27
|
+
|
|
28
|
+
return self._query_runner.call_procedure(endpoint, params, yields, database, logging, custom_error)
|
|
29
|
+
|
|
30
|
+
def call_function(self, endpoint: str, params: Optional[CallParameters] = None) -> Any:
|
|
31
|
+
return self._query_runner.call_function(endpoint, params)
|
|
32
|
+
|
|
33
|
+
def server_version(self) -> ServerVersion:
|
|
34
|
+
return self._query_runner.server_version()
|
|
35
|
+
|
|
36
|
+
def create_graph_constructor(
|
|
37
|
+
self, graph_name: str, concurrency: int, undirected_relationship_types: Optional[list[str]]
|
|
38
|
+
) -> GraphConstructor:
|
|
39
|
+
return self._query_runner.create_graph_constructor(graph_name, concurrency, undirected_relationship_types)
|
|
40
|
+
|
|
41
|
+
def set_show_progress(self, show_progress: bool) -> None:
|
|
42
|
+
self._query_runner.set_show_progress(show_progress)
|
|
43
|
+
|
|
44
|
+
def encrypted(self) -> bool:
|
|
45
|
+
return self._query_runner.encrypted()
|
|
46
|
+
|
|
47
|
+
def close(self) -> None:
|
|
48
|
+
self._query_runner.close()
|
|
49
|
+
|
|
50
|
+
def database(self) -> Optional[str]:
|
|
51
|
+
return "neo4j"
|
|
52
|
+
|
|
53
|
+
def run_cypher(
|
|
54
|
+
self,
|
|
55
|
+
query: str,
|
|
56
|
+
params: Optional[dict[str, Any]] = None,
|
|
57
|
+
database: Optional[str] = None,
|
|
58
|
+
custom_error: bool = True,
|
|
59
|
+
) -> DataFrame:
|
|
60
|
+
raise NotImplementedError
|
|
61
|
+
|
|
62
|
+
def driver_config(self) -> dict[str, Any]:
|
|
63
|
+
raise NotImplementedError
|
|
64
|
+
|
|
65
|
+
def set_database(self, database: str) -> None:
|
|
66
|
+
raise NotImplementedError
|
|
67
|
+
|
|
68
|
+
def set_bookmarks(self, bookmarks: Optional[Any]) -> None:
|
|
69
|
+
raise NotImplementedError
|
|
70
|
+
|
|
71
|
+
def bookmarks(self) -> Optional[Any]:
|
|
72
|
+
raise NotImplementedError
|
|
73
|
+
|
|
74
|
+
def last_bookmarks(self) -> Optional[Any]:
|
|
75
|
+
raise NotImplementedError
|
|
76
|
+
|
|
77
|
+
def set_server_version(self, _: ServerVersion) -> None:
|
|
78
|
+
super().set_server_version(_)
|
|
79
|
+
|
|
80
|
+
def clone(self, host: str, port: int) -> QueryRunner:
|
|
81
|
+
return self
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from .algorithm_category import AlgorithmCategory
|
|
2
|
+
from .aura_api import AuraApiError, SessionStatusError
|
|
2
3
|
from .cloud_location import CloudLocation
|
|
3
4
|
from .dbms_connection_info import DbmsConnectionInfo
|
|
4
5
|
from .gds_sessions import AuraAPICredentials, GdsSessions
|
|
@@ -14,4 +15,6 @@ __all__ = [
|
|
|
14
15
|
"SessionMemory",
|
|
15
16
|
"SessionMemoryValue",
|
|
16
17
|
"AlgorithmCategory",
|
|
18
|
+
"SessionStatusError",
|
|
19
|
+
"AuraApiError",
|
|
17
20
|
]
|