graphdatascience 1.10a1__tar.gz → 1.11a1__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.10a1/graphdatascience.egg-info → graphdatascience-1.11a1}/PKG-INFO +2 -2
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/base_graph_proc_runner.py +4 -4
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_entity_ops_runner.py +42 -5
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_remote_project_runner.py +3 -5
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph_data_science.py +13 -10
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/query_runner/arrow_graph_constructor.py +6 -2
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/query_runner/arrow_query_runner.py +21 -5
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/query_runner/neo4j_query_runner.py +36 -15
- graphdatascience-1.11a1/graphdatascience/session/__init__.py +16 -0
- graphdatascience-1.11a1/graphdatascience/session/algorithm_category.py +14 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/session/aura_api.py +101 -106
- graphdatascience-1.11a1/graphdatascience/session/aura_api_responses.py +166 -0
- graphdatascience-1.11a1/graphdatascience/session/aurads_sessions.py +202 -0
- graphdatascience-1.11a1/graphdatascience/session/dedicated_sessions.py +137 -0
- graphdatascience-1.11a1/graphdatascience/session/gds_sessions.py +107 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/session/schema.py +0 -3
- graphdatascience-1.11a1/graphdatascience/session/session_info.py +40 -0
- graphdatascience-1.11a1/graphdatascience/session/session_sizes.py +31 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/system/system_endpoints.py +2 -2
- graphdatascience-1.11a1/graphdatascience/version.py +1 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1/graphdatascience.egg-info}/PKG-INFO +2 -2
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience.egg-info/SOURCES.txt +5 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience.egg-info/requires.txt +1 -1
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/requirements/base/base.txt +1 -1
- graphdatascience-1.10a1/graphdatascience/session/__init__.py +0 -13
- graphdatascience-1.10a1/graphdatascience/session/gds_sessions.py +0 -240
- graphdatascience-1.10a1/graphdatascience/session/session_sizes.py +0 -33
- graphdatascience-1.10a1/graphdatascience/version.py +0 -1
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/LICENSE +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/MANIFEST.in +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/README.md +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/__init__.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/algo/__init__.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/algo/algo_endpoints.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/algo/algo_proc_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/algo/single_mode_algo_endpoints.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/call_builder.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/call_parameters.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/caller_base.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/endpoints.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/error/__init__.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/error/client_only_endpoint.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/error/cypher_warning_handler.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/error/endpoint_suggester.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/error/gds_not_installed.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/error/illegal_attr_checker.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/error/unable_to_connect.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/error/uncallable_namespace.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/__init__.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_alpha_proc_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_beta_proc_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_create_result.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_cypher_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_endpoints.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_export_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_object.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_proc_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_project_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_remote_proc_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_sample_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_type_check.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/nx_loader.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/ogb_loader.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/ignored_server_endpoints.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/__init__.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/graphsage_model.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/link_prediction_model.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/model.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/model_alpha_proc_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/model_beta_proc_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/model_endpoints.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/model_proc_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/model_resolver.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/node_classification_model.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/node_regression_model.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/pipeline_model.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/simple_rel_embedding_model.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/__init__.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/classification_training_pipeline.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/lp_pipeline_create_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/lp_training_pipeline.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/nc_pipeline_create_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/nc_training_pipeline.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/nr_pipeline_create_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/nr_training_pipeline.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/pipeline_alpha_proc_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/pipeline_beta_proc_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/pipeline_endpoints.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/pipeline_proc_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/training_pipeline.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/py.typed +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/query_runner/__init__.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/query_runner/arrow_endpoint_version.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/query_runner/aura_db_arrow_query_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/query_runner/cypher_graph_constructor.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/query_runner/graph_constructor.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/query_runner/query_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/__init__.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/cora/__init__.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/cora/cora_nodes.parquet.gzip +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/cora/cora_rels.parquet.gzip +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/cora/serialize_cora.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/imdb/__init__.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/imdb/imdb_acted_in.parquet.gzip +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/imdb/imdb_actors.parquet.gzip +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/imdb/imdb_directed_in.parquet.gzip +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/imdb/imdb_directors.parquet.gzip +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/imdb/imdb_movies_with_genre.parquet.gzip +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/imdb/imdb_movies_without_genre.parquet.gzip +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/imdb/serialize_imdb.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/karate/__init__.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/karate/karate_club.parquet.gzip +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/lastfm/__init__.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/lastfm/artist_nodes.parquet.gzip +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/lastfm/serialize_lastfm.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/lastfm/user_friend_df_directed.parquet.gzip +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/lastfm/user_listen_artist_rels.parquet.gzip +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/lastfm/user_nodes.parquet.gzip +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/lastfm/user_tag_artist_rels.parquet.gzip +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/server_version/__init__.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/server_version/compatible_with.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/server_version/server_version.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/session/aura_graph_data_science.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/session/dbms_connection_info.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/session/region_suggester.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/system/__init__.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/system/config_endpoints.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/topological_lp/__init__.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/topological_lp/topological_lp_alpha_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/topological_lp/topological_lp_endpoints.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/utils/__init__.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/utils/util_endpoints.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/utils/util_proc_runner.py +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience.egg-info/dependency_links.txt +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience.egg-info/not-zip-safe +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience.egg-info/top_level.txt +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/pyproject.toml +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/requirements/base/networkx.txt +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/requirements/base/ogb.txt +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/setup.cfg +0 -0
- {graphdatascience-1.10a1 → graphdatascience-1.11a1}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: graphdatascience
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.11a1
|
|
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
|
|
@@ -31,7 +31,7 @@ License-File: LICENSE
|
|
|
31
31
|
Requires-Dist: multimethod<2.0,>=1.0
|
|
32
32
|
Requires-Dist: neo4j<6.0,>=4.4.2
|
|
33
33
|
Requires-Dist: pandas<3.0,>=1.0
|
|
34
|
-
Requires-Dist: pyarrow<
|
|
34
|
+
Requires-Dist: pyarrow<16.0,>=11.0
|
|
35
35
|
Requires-Dist: textdistance<5.0,>=4.0
|
|
36
36
|
Requires-Dist: tqdm<5.0,>=4.0
|
|
37
37
|
Requires-Dist: typing-extensions<5.0,>=4.0
|
{graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/base_graph_proc_runner.py
RENAMED
|
@@ -18,6 +18,7 @@ from .graph_entity_ops_runner import (
|
|
|
18
18
|
GraphElementPropertyRunner,
|
|
19
19
|
GraphLabelRunner,
|
|
20
20
|
GraphNodePropertiesRunner,
|
|
21
|
+
GraphNodePropertyRunner,
|
|
21
22
|
GraphPropertyRunner,
|
|
22
23
|
GraphRelationshipPropertiesRunner,
|
|
23
24
|
GraphRelationshipRunner,
|
|
@@ -379,9 +380,9 @@ class BaseGraphProcRunner(UncallableNamespace, IllegalAttrChecker):
|
|
|
379
380
|
)
|
|
380
381
|
|
|
381
382
|
@property
|
|
382
|
-
def nodeProperty(self) ->
|
|
383
|
+
def nodeProperty(self) -> GraphNodePropertyRunner:
|
|
383
384
|
self._namespace += ".nodeProperty"
|
|
384
|
-
return
|
|
385
|
+
return GraphNodePropertyRunner(self._query_runner, self._namespace, self._server_version)
|
|
385
386
|
|
|
386
387
|
@property
|
|
387
388
|
def nodeProperties(self) -> GraphNodePropertiesRunner:
|
|
@@ -516,8 +517,7 @@ class BaseGraphProcRunner(UncallableNamespace, IllegalAttrChecker):
|
|
|
516
517
|
).squeeze()
|
|
517
518
|
|
|
518
519
|
@multimethod
|
|
519
|
-
def removeNodeProperties(self) -> None:
|
|
520
|
-
...
|
|
520
|
+
def removeNodeProperties(self) -> None: ...
|
|
521
521
|
|
|
522
522
|
@removeNodeProperties.register
|
|
523
523
|
@graph_type_check
|
|
@@ -77,6 +77,26 @@ class GraphElementPropertyRunner(GraphEntityOpsBaseRunner):
|
|
|
77
77
|
return self._handle_properties(G, node_properties, node_labels, config)
|
|
78
78
|
|
|
79
79
|
|
|
80
|
+
class GraphNodePropertyRunner(GraphEntityOpsBaseRunner):
|
|
81
|
+
@compatible_with("stream", min_inclusive=ServerVersion(2, 2, 0))
|
|
82
|
+
@filter_id_func_deprecation_warning()
|
|
83
|
+
def stream(
|
|
84
|
+
self,
|
|
85
|
+
G: Graph,
|
|
86
|
+
node_property: str,
|
|
87
|
+
node_labels: Strings = ["*"],
|
|
88
|
+
db_node_properties: List[str] = [],
|
|
89
|
+
**config: Any,
|
|
90
|
+
) -> DataFrame:
|
|
91
|
+
self._namespace += ".stream"
|
|
92
|
+
|
|
93
|
+
result = self._handle_properties(G, node_property, node_labels, config)
|
|
94
|
+
|
|
95
|
+
return GraphNodePropertiesRunner._process_result(
|
|
96
|
+
self._query_runner, list(node_property), False, db_node_properties, result, config
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
80
100
|
class GraphNodePropertiesRunner(GraphEntityOpsBaseRunner):
|
|
81
101
|
@compatible_with("stream", min_inclusive=ServerVersion(2, 2, 0))
|
|
82
102
|
@filter_id_func_deprecation_warning()
|
|
@@ -93,6 +113,19 @@ class GraphNodePropertiesRunner(GraphEntityOpsBaseRunner):
|
|
|
93
113
|
|
|
94
114
|
result = self._handle_properties(G, node_properties, node_labels, config)
|
|
95
115
|
|
|
116
|
+
return GraphNodePropertiesRunner._process_result(
|
|
117
|
+
self._query_runner, node_properties, separate_property_columns, db_node_properties, result, config
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
@staticmethod
|
|
121
|
+
def _process_result(
|
|
122
|
+
query_runner: QueryRunner,
|
|
123
|
+
node_properties: List[str],
|
|
124
|
+
separate_property_columns: bool,
|
|
125
|
+
db_node_properties: List[str],
|
|
126
|
+
result: DataFrame,
|
|
127
|
+
config: Dict[str, Any],
|
|
128
|
+
) -> DataFrame:
|
|
96
129
|
# new format was requested, but the query was run via Cypher
|
|
97
130
|
if separate_property_columns and "propertyValue" in result.keys():
|
|
98
131
|
wide_result = result.pivot(index=["nodeId"], columns=["nodeProperty"], values="propertyValue")
|
|
@@ -106,7 +139,7 @@ class GraphNodePropertiesRunner(GraphEntityOpsBaseRunner):
|
|
|
106
139
|
# old format was requested but the query was run via Arrow
|
|
107
140
|
elif not separate_property_columns and "propertyValue" not in result.keys():
|
|
108
141
|
id_vars = ["nodeId", "nodeLabels"] if config.get("listNodeLabels", False) else ["nodeId"]
|
|
109
|
-
result = result.melt(id_vars=id_vars
|
|
142
|
+
result = result.melt(id_vars=id_vars, var_name="nodeProperty", value_name="propertyValue")
|
|
110
143
|
|
|
111
144
|
if db_node_properties:
|
|
112
145
|
duplicate_properties = set(db_node_properties).intersection(set(node_properties))
|
|
@@ -116,16 +149,20 @@ class GraphNodePropertiesRunner(GraphEntityOpsBaseRunner):
|
|
|
116
149
|
)
|
|
117
150
|
|
|
118
151
|
unique_node_ids = result["nodeId"].drop_duplicates().tolist()
|
|
119
|
-
db_properties_df =
|
|
120
|
-
|
|
152
|
+
db_properties_df = query_runner.run_cypher(
|
|
153
|
+
GraphNodePropertiesRunner._build_query(db_node_properties), {"ids": unique_node_ids}
|
|
121
154
|
)
|
|
122
155
|
|
|
123
156
|
if "propertyValue" not in result.keys():
|
|
124
157
|
result = result.join(db_properties_df.set_index("nodeId"), on="nodeId")
|
|
125
158
|
else:
|
|
126
|
-
db_properties_df = db_properties_df.melt(
|
|
127
|
-
|
|
159
|
+
db_properties_df = db_properties_df.melt(
|
|
160
|
+
id_vars=["nodeId"], var_name="nodeProperty", value_name="propertyValue"
|
|
128
161
|
)
|
|
162
|
+
|
|
163
|
+
if "nodeProperty" not in result.keys():
|
|
164
|
+
result["nodeProperty"] = node_properties[0]
|
|
165
|
+
|
|
129
166
|
result = pd.concat([result, db_properties_df])
|
|
130
167
|
|
|
131
168
|
return result
|
|
@@ -8,13 +8,11 @@ from .graph_object import Graph
|
|
|
8
8
|
from graphdatascience.call_parameters import CallParameters
|
|
9
9
|
from graphdatascience.graph.graph_create_result import GraphCreateResult
|
|
10
10
|
from graphdatascience.server_version.server_version import ServerVersion
|
|
11
|
-
from graphdatascience.session.schema import (
|
|
12
|
-
NODE_PROPERTY_SCHEMA,
|
|
13
|
-
RELATIONSHIP_PROPERTY_SCHEMA,
|
|
14
|
-
)
|
|
15
11
|
|
|
16
12
|
|
|
17
13
|
class GraphProjectRemoteRunner(IllegalAttrChecker):
|
|
14
|
+
_SCHEMA_KEYS = ["nodePropertySchema", "relationshipPropertySchema"]
|
|
15
|
+
|
|
18
16
|
@compatible_with("project", min_inclusive=ServerVersion(2, 6, 0))
|
|
19
17
|
def __call__(self, graph_name: str, query: str, **config: Any) -> GraphCreateResult:
|
|
20
18
|
placeholder = "<>" # host and token will be added by query runner
|
|
@@ -35,6 +33,6 @@ class GraphProjectRemoteRunner(IllegalAttrChecker):
|
|
|
35
33
|
|
|
36
34
|
@staticmethod
|
|
37
35
|
def map_property_types(config: dict[str, Any]) -> None:
|
|
38
|
-
for key in
|
|
36
|
+
for key in GraphProjectRemoteRunner._SCHEMA_KEYS:
|
|
39
37
|
if key in config:
|
|
40
38
|
config[key] = {k: v.value for k, v in config[key].items()}
|
|
@@ -23,11 +23,12 @@ class GraphDataScience(DirectEndpoints, UncallableNamespace):
|
|
|
23
23
|
|
|
24
24
|
def __init__(
|
|
25
25
|
self,
|
|
26
|
+
/,
|
|
26
27
|
endpoint: Union[str, Driver, QueryRunner],
|
|
27
28
|
auth: Optional[Tuple[str, str]] = None,
|
|
28
29
|
aura_ds: bool = False,
|
|
29
30
|
database: Optional[str] = None,
|
|
30
|
-
arrow: bool = True,
|
|
31
|
+
arrow: Union[str, bool] = True,
|
|
31
32
|
arrow_disable_server_verification: bool = True,
|
|
32
33
|
arrow_tls_root_certs: Optional[bytes] = None,
|
|
33
34
|
bookmarks: Optional[Any] = None,
|
|
@@ -43,19 +44,20 @@ class GraphDataScience(DirectEndpoints, UncallableNamespace):
|
|
|
43
44
|
A username, password pair for database authentication.
|
|
44
45
|
aura_ds : bool, default False
|
|
45
46
|
A flag that indicates that that the client is used to connect
|
|
46
|
-
to a Neo4j
|
|
47
|
+
to a Neo4j AuraDS instance.
|
|
47
48
|
database: Optional[str], default None
|
|
48
49
|
The Neo4j database to query against.
|
|
49
|
-
arrow : bool, default True
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
arrow : Union[str, bool], default True
|
|
51
|
+
Arrow connection information. This is either a bool or a string.
|
|
52
|
+
If it is a string, it will be interpreted as a connection URL to a GDS Arrow Server.
|
|
53
|
+
If it is a bool,
|
|
54
|
+
True will make the client discover the connection URI to the GDS Arrow server via the Neo4j endpoint,
|
|
55
|
+
while False will make the client use Bolt for all operations.
|
|
52
56
|
arrow_disable_server_verification : bool, default True
|
|
53
|
-
A flag that
|
|
54
|
-
TLS, that it skips server verification. If this is enabled, all
|
|
55
|
-
other TLS settings are overridden.
|
|
57
|
+
A flag that overrides other TLS settings and disables server verification for TLS connections.
|
|
56
58
|
arrow_tls_root_certs : Optional[bytes], default None
|
|
57
|
-
PEM-encoded certificates that are used for the
|
|
58
|
-
Arrow Flight server.
|
|
59
|
+
PEM-encoded certificates that are used for the connection to the
|
|
60
|
+
GDS Arrow Flight server.
|
|
59
61
|
bookmarks : Optional[Any], default None
|
|
60
62
|
The Neo4j bookmarks to require a certain state before the next query gets executed.
|
|
61
63
|
"""
|
|
@@ -76,6 +78,7 @@ class GraphDataScience(DirectEndpoints, UncallableNamespace):
|
|
|
76
78
|
self._query_runner.encrypted(),
|
|
77
79
|
arrow_disable_server_verification,
|
|
78
80
|
arrow_tls_root_certs,
|
|
81
|
+
None if arrow is True else arrow,
|
|
79
82
|
)
|
|
80
83
|
|
|
81
84
|
super().__init__(self._query_runner, "gds", self._server_version)
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import concurrent
|
|
2
4
|
import json
|
|
3
5
|
import math
|
|
4
6
|
import warnings
|
|
5
7
|
from concurrent.futures import ThreadPoolExecutor
|
|
6
|
-
from typing import Any, Dict, List, Optional
|
|
8
|
+
from typing import Any, Dict, List, NoReturn, Optional
|
|
7
9
|
|
|
8
10
|
import numpy
|
|
9
11
|
import pyarrow.flight as flight
|
|
@@ -93,7 +95,7 @@ class ArrowGraphConstructor(GraphConstructor):
|
|
|
93
95
|
|
|
94
96
|
json.loads(collected_result[0].body.to_pybytes().decode())
|
|
95
97
|
|
|
96
|
-
def _send_df(self, df: DataFrame, entity_type: str, pbar: tqdm) -> None:
|
|
98
|
+
def _send_df(self, df: DataFrame, entity_type: str, pbar: tqdm[NoReturn]) -> None:
|
|
97
99
|
table = Table.from_pandas(df)
|
|
98
100
|
batches = table.to_batches(self._chunk_size)
|
|
99
101
|
flight_descriptor = {"name": self._graph_name, "entity_type": entity_type}
|
|
@@ -108,6 +110,8 @@ class ArrowGraphConstructor(GraphConstructor):
|
|
|
108
110
|
for partition in batches:
|
|
109
111
|
writer.write_batch(partition)
|
|
110
112
|
pbar.update(partition.num_rows)
|
|
113
|
+
# Force a refresh to avoid the progress bar getting stuck at 0%
|
|
114
|
+
pbar.refresh()
|
|
111
115
|
|
|
112
116
|
def _send_dfs(self, dfs: List[DataFrame], entity_type: str) -> None:
|
|
113
117
|
desc = "Uploading Nodes" if entity_type == "node" else "Uploading Relationships"
|
|
@@ -31,17 +31,22 @@ class ArrowQueryRunner(QueryRunner):
|
|
|
31
31
|
encrypted: bool = False,
|
|
32
32
|
disable_server_verification: bool = False,
|
|
33
33
|
tls_root_certs: Optional[bytes] = None,
|
|
34
|
+
connection_string_override: Optional[str] = None,
|
|
34
35
|
) -> QueryRunner:
|
|
35
36
|
arrow_info = (
|
|
36
37
|
fallback_query_runner.call_procedure(endpoint="gds.debug.arrow", custom_error=False).squeeze().to_dict()
|
|
37
38
|
)
|
|
38
39
|
server_version = fallback_query_runner.server_version()
|
|
39
|
-
|
|
40
|
+
connection_string: str
|
|
41
|
+
if connection_string_override is not None:
|
|
42
|
+
connection_string = connection_string_override
|
|
43
|
+
else:
|
|
44
|
+
connection_string = arrow_info.get("advertisedListenAddress", arrow_info["listenAddress"])
|
|
40
45
|
arrow_endpoint_version = ArrowEndpointVersion.from_arrow_info(arrow_info.get("versions", []))
|
|
41
46
|
|
|
42
47
|
if arrow_info["running"]:
|
|
43
48
|
return ArrowQueryRunner(
|
|
44
|
-
|
|
49
|
+
connection_string,
|
|
45
50
|
fallback_query_runner,
|
|
46
51
|
server_version,
|
|
47
52
|
auth,
|
|
@@ -277,7 +282,7 @@ class ArrowQueryRunner(QueryRunner):
|
|
|
277
282
|
|
|
278
283
|
if self._arrow_endpoint_version == ArrowEndpointVersion.V1:
|
|
279
284
|
payload = {
|
|
280
|
-
"name": "
|
|
285
|
+
"name": "GET_COMMAND",
|
|
281
286
|
"version": ArrowEndpointVersion.V1.version(),
|
|
282
287
|
"body": payload,
|
|
283
288
|
}
|
|
@@ -320,6 +325,10 @@ class ArrowQueryRunner(QueryRunner):
|
|
|
320
325
|
)
|
|
321
326
|
|
|
322
327
|
def _sanitize_arrow_table(self, arrow_table: Table) -> Table:
|
|
328
|
+
# empty columns cannot be used to build a chunked_array in pyarrow
|
|
329
|
+
if len(arrow_table) == 0:
|
|
330
|
+
return arrow_table
|
|
331
|
+
|
|
323
332
|
dict_encoded_fields = [
|
|
324
333
|
(idx, field) for idx, field in enumerate(arrow_table.schema) if is_dictionary(field.type)
|
|
325
334
|
]
|
|
@@ -368,10 +377,17 @@ class AuthMiddleware(ClientMiddleware): # type: ignore
|
|
|
368
377
|
self._factory = factory
|
|
369
378
|
|
|
370
379
|
def received_headers(self, headers: Dict[str, Any]) -> None:
|
|
371
|
-
auth_header
|
|
380
|
+
auth_header = headers.get("authorization", None)
|
|
372
381
|
if not auth_header:
|
|
373
382
|
return
|
|
374
|
-
|
|
383
|
+
|
|
384
|
+
# the result is always a list
|
|
385
|
+
header_value = auth_header[0]
|
|
386
|
+
|
|
387
|
+
if not isinstance(header_value, str):
|
|
388
|
+
raise ValueError(f"Incompatible header value received from server: `{header_value}`")
|
|
389
|
+
|
|
390
|
+
auth_type, token = header_value.split(" ", 1)
|
|
375
391
|
if auth_type == "Bearer":
|
|
376
392
|
self._factory.set_token(token)
|
|
377
393
|
|
|
@@ -5,7 +5,7 @@ import re
|
|
|
5
5
|
import time
|
|
6
6
|
import warnings
|
|
7
7
|
from concurrent.futures import Future, ThreadPoolExecutor, wait
|
|
8
|
-
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
8
|
+
from typing import Any, Dict, List, NoReturn, Optional, Tuple, Union
|
|
9
9
|
from uuid import uuid4
|
|
10
10
|
|
|
11
11
|
import neo4j
|
|
@@ -46,18 +46,20 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
46
46
|
driver = neo4j.GraphDatabase.driver(endpoint, auth=auth, **config)
|
|
47
47
|
|
|
48
48
|
query_runner = Neo4jQueryRunner(
|
|
49
|
-
driver,
|
|
49
|
+
driver,
|
|
50
|
+
auto_close=True,
|
|
51
|
+
bookmarks=bookmarks,
|
|
52
|
+
config=config,
|
|
53
|
+
server_version=server_version,
|
|
54
|
+
database=database,
|
|
50
55
|
)
|
|
51
56
|
|
|
52
57
|
elif isinstance(endpoint, neo4j.Driver):
|
|
53
|
-
query_runner = Neo4jQueryRunner(endpoint, auto_close=False, bookmarks=bookmarks)
|
|
58
|
+
query_runner = Neo4jQueryRunner(endpoint, auto_close=False, bookmarks=bookmarks, database=database)
|
|
54
59
|
|
|
55
60
|
else:
|
|
56
61
|
raise ValueError(f"Invalid endpoint type: {type(endpoint)}")
|
|
57
62
|
|
|
58
|
-
if database:
|
|
59
|
-
query_runner.set_database(database)
|
|
60
|
-
|
|
61
63
|
return query_runner
|
|
62
64
|
|
|
63
65
|
@staticmethod
|
|
@@ -97,7 +99,7 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
97
99
|
if database is None:
|
|
98
100
|
database = self._database
|
|
99
101
|
|
|
100
|
-
self._verify_connectivity()
|
|
102
|
+
self._verify_connectivity(database=database)
|
|
101
103
|
|
|
102
104
|
with self._driver.session(database=database, bookmarks=self.bookmarks()) as session:
|
|
103
105
|
try:
|
|
@@ -224,14 +226,19 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
224
226
|
self._logger.info(notification)
|
|
225
227
|
|
|
226
228
|
def _log(self, job_id: str, future: "Future[Any]", database: Optional[str] = None) -> None:
|
|
227
|
-
pbar = None
|
|
229
|
+
pbar: Optional[tqdm[NoReturn]] = None
|
|
228
230
|
warn_if_failure = True
|
|
229
231
|
|
|
230
232
|
while wait([future], timeout=self._LOG_POLLING_INTERVAL).not_done:
|
|
231
233
|
try:
|
|
232
234
|
tier = "beta." if self._server_version < ServerVersion(2, 5, 0) else ""
|
|
235
|
+
# we only retrieve the progress of the root task
|
|
233
236
|
progress = self.run_cypher(
|
|
234
|
-
f"CALL gds.{tier}listProgress('{job_id}')
|
|
237
|
+
f"CALL gds.{tier}listProgress('{job_id}')"
|
|
238
|
+
+ " YIELD taskName, progress"
|
|
239
|
+
+ " RETURN taskName, progress"
|
|
240
|
+
+ " LIMIT 1",
|
|
241
|
+
database=database,
|
|
235
242
|
)
|
|
236
243
|
except Exception as e:
|
|
237
244
|
# Do nothing if the procedure either:
|
|
@@ -246,17 +253,19 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
246
253
|
continue
|
|
247
254
|
|
|
248
255
|
progress_percent = progress["progress"][0]
|
|
249
|
-
if
|
|
250
|
-
task_name = progress["taskName"][0].split("|--")[-1][1:]
|
|
251
|
-
pbar = pbar or tqdm(total=100, unit="%", desc=task_name)
|
|
252
|
-
else:
|
|
256
|
+
if progress_percent == "n/a":
|
|
253
257
|
return
|
|
254
258
|
|
|
259
|
+
root_task_name = progress["taskName"][0].split("|--")[-1][1:]
|
|
260
|
+
if not pbar:
|
|
261
|
+
pbar = tqdm(total=100, unit="%", desc=root_task_name, maxinterval=self._LOG_POLLING_INTERVAL)
|
|
262
|
+
|
|
255
263
|
parsed_progress = float(progress_percent[:-1])
|
|
256
264
|
pbar.update(parsed_progress - pbar.n)
|
|
257
265
|
|
|
258
266
|
if pbar:
|
|
259
267
|
pbar.update(100 - pbar.n)
|
|
268
|
+
pbar.refresh()
|
|
260
269
|
|
|
261
270
|
def set_database(self, database: str) -> None:
|
|
262
271
|
self._database = database
|
|
@@ -303,11 +312,14 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
303
312
|
|
|
304
313
|
raise SyntaxError(generate_suggestive_error_message(requested_endpoint, all_endpoints)) from e
|
|
305
314
|
|
|
306
|
-
def _verify_connectivity(self) -> None:
|
|
315
|
+
def _verify_connectivity(self, database: Optional[str] = None) -> None:
|
|
307
316
|
WAIT_TIME = 1
|
|
308
317
|
MAX_RETRYS = 10 * 60
|
|
309
318
|
WARN_INTERVAL = 10
|
|
310
319
|
|
|
320
|
+
if database is None:
|
|
321
|
+
database = self._database
|
|
322
|
+
|
|
311
323
|
exception = None
|
|
312
324
|
retrys = 0
|
|
313
325
|
while retrys < MAX_RETRYS:
|
|
@@ -318,7 +330,16 @@ class Neo4jQueryRunner(QueryRunner):
|
|
|
318
330
|
category=neo4j.ExperimentalWarning,
|
|
319
331
|
message=r"^The configuration may change in the future.$",
|
|
320
332
|
)
|
|
321
|
-
|
|
333
|
+
else:
|
|
334
|
+
warnings.filterwarnings(
|
|
335
|
+
"ignore",
|
|
336
|
+
category=neo4j.ExperimentalWarning,
|
|
337
|
+
message=(
|
|
338
|
+
r"^All configuration key-word arguments to verify_connectivity\(\) are experimental. "
|
|
339
|
+
"They might be changed or removed in any future version without prior notice.$"
|
|
340
|
+
),
|
|
341
|
+
)
|
|
342
|
+
self._driver.verify_connectivity(database=database)
|
|
322
343
|
break
|
|
323
344
|
except neo4j.exceptions.DriverError as e:
|
|
324
345
|
exception = e
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from .algorithm_category import AlgorithmCategory
|
|
2
|
+
from .dbms_connection_info import DbmsConnectionInfo
|
|
3
|
+
from .gds_sessions import AuraAPICredentials, GdsSessions
|
|
4
|
+
from .schema import GdsPropertyTypes
|
|
5
|
+
from .session_info import SessionInfo
|
|
6
|
+
from .session_sizes import SessionMemory
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"GdsSessions",
|
|
10
|
+
"SessionInfo",
|
|
11
|
+
"DbmsConnectionInfo",
|
|
12
|
+
"AuraAPICredentials",
|
|
13
|
+
"SessionMemory",
|
|
14
|
+
"GdsPropertyTypes",
|
|
15
|
+
"AlgorithmCategory",
|
|
16
|
+
]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class AlgorithmCategory(Enum):
|
|
5
|
+
"""
|
|
6
|
+
Enumeration of supported algorithm categories used for size estimation.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
CENTRALITY = "centrality"
|
|
10
|
+
COMMUNITY_DETECTION = "community-detection"
|
|
11
|
+
MACHINE_LEARNING = "machine-learning"
|
|
12
|
+
NODE_EMBEDDING = "node-embedding"
|
|
13
|
+
PATH_FINDING = "path-finding"
|
|
14
|
+
SIMILARITY = "similarity"
|