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.
Files changed (141) hide show
  1. {graphdatascience-1.10a1/graphdatascience.egg-info → graphdatascience-1.11a1}/PKG-INFO +2 -2
  2. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/base_graph_proc_runner.py +4 -4
  3. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_entity_ops_runner.py +42 -5
  4. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_remote_project_runner.py +3 -5
  5. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph_data_science.py +13 -10
  6. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/query_runner/arrow_graph_constructor.py +6 -2
  7. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/query_runner/arrow_query_runner.py +21 -5
  8. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/query_runner/neo4j_query_runner.py +36 -15
  9. graphdatascience-1.11a1/graphdatascience/session/__init__.py +16 -0
  10. graphdatascience-1.11a1/graphdatascience/session/algorithm_category.py +14 -0
  11. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/session/aura_api.py +101 -106
  12. graphdatascience-1.11a1/graphdatascience/session/aura_api_responses.py +166 -0
  13. graphdatascience-1.11a1/graphdatascience/session/aurads_sessions.py +202 -0
  14. graphdatascience-1.11a1/graphdatascience/session/dedicated_sessions.py +137 -0
  15. graphdatascience-1.11a1/graphdatascience/session/gds_sessions.py +107 -0
  16. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/session/schema.py +0 -3
  17. graphdatascience-1.11a1/graphdatascience/session/session_info.py +40 -0
  18. graphdatascience-1.11a1/graphdatascience/session/session_sizes.py +31 -0
  19. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/system/system_endpoints.py +2 -2
  20. graphdatascience-1.11a1/graphdatascience/version.py +1 -0
  21. {graphdatascience-1.10a1 → graphdatascience-1.11a1/graphdatascience.egg-info}/PKG-INFO +2 -2
  22. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience.egg-info/SOURCES.txt +5 -0
  23. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience.egg-info/requires.txt +1 -1
  24. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/requirements/base/base.txt +1 -1
  25. graphdatascience-1.10a1/graphdatascience/session/__init__.py +0 -13
  26. graphdatascience-1.10a1/graphdatascience/session/gds_sessions.py +0 -240
  27. graphdatascience-1.10a1/graphdatascience/session/session_sizes.py +0 -33
  28. graphdatascience-1.10a1/graphdatascience/version.py +0 -1
  29. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/LICENSE +0 -0
  30. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/MANIFEST.in +0 -0
  31. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/README.md +0 -0
  32. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/__init__.py +0 -0
  33. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/algo/__init__.py +0 -0
  34. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/algo/algo_endpoints.py +0 -0
  35. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/algo/algo_proc_runner.py +0 -0
  36. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/algo/single_mode_algo_endpoints.py +0 -0
  37. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/call_builder.py +0 -0
  38. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/call_parameters.py +0 -0
  39. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/caller_base.py +0 -0
  40. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/endpoints.py +0 -0
  41. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/error/__init__.py +0 -0
  42. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/error/client_only_endpoint.py +0 -0
  43. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/error/cypher_warning_handler.py +0 -0
  44. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/error/endpoint_suggester.py +0 -0
  45. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/error/gds_not_installed.py +0 -0
  46. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/error/illegal_attr_checker.py +0 -0
  47. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/error/unable_to_connect.py +0 -0
  48. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/error/uncallable_namespace.py +0 -0
  49. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/__init__.py +0 -0
  50. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_alpha_proc_runner.py +0 -0
  51. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_beta_proc_runner.py +0 -0
  52. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_create_result.py +0 -0
  53. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_cypher_runner.py +0 -0
  54. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_endpoints.py +0 -0
  55. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_export_runner.py +0 -0
  56. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_object.py +0 -0
  57. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_proc_runner.py +0 -0
  58. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_project_runner.py +0 -0
  59. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_remote_proc_runner.py +0 -0
  60. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_sample_runner.py +0 -0
  61. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/graph_type_check.py +0 -0
  62. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/nx_loader.py +0 -0
  63. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/graph/ogb_loader.py +0 -0
  64. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/ignored_server_endpoints.py +0 -0
  65. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/__init__.py +0 -0
  66. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/graphsage_model.py +0 -0
  67. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/link_prediction_model.py +0 -0
  68. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/model.py +0 -0
  69. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/model_alpha_proc_runner.py +0 -0
  70. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/model_beta_proc_runner.py +0 -0
  71. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/model_endpoints.py +0 -0
  72. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/model_proc_runner.py +0 -0
  73. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/model_resolver.py +0 -0
  74. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/node_classification_model.py +0 -0
  75. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/node_regression_model.py +0 -0
  76. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/pipeline_model.py +0 -0
  77. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/model/simple_rel_embedding_model.py +0 -0
  78. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/__init__.py +0 -0
  79. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/classification_training_pipeline.py +0 -0
  80. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/lp_pipeline_create_runner.py +0 -0
  81. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/lp_training_pipeline.py +0 -0
  82. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/nc_pipeline_create_runner.py +0 -0
  83. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/nc_training_pipeline.py +0 -0
  84. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/nr_pipeline_create_runner.py +0 -0
  85. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/nr_training_pipeline.py +0 -0
  86. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/pipeline_alpha_proc_runner.py +0 -0
  87. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/pipeline_beta_proc_runner.py +0 -0
  88. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/pipeline_endpoints.py +0 -0
  89. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/pipeline_proc_runner.py +0 -0
  90. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/pipeline/training_pipeline.py +0 -0
  91. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/py.typed +0 -0
  92. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/query_runner/__init__.py +0 -0
  93. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/query_runner/arrow_endpoint_version.py +0 -0
  94. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/query_runner/aura_db_arrow_query_runner.py +0 -0
  95. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/query_runner/cypher_graph_constructor.py +0 -0
  96. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/query_runner/graph_constructor.py +0 -0
  97. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/query_runner/query_runner.py +0 -0
  98. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/__init__.py +0 -0
  99. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/cora/__init__.py +0 -0
  100. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/cora/cora_nodes.parquet.gzip +0 -0
  101. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/cora/cora_rels.parquet.gzip +0 -0
  102. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/cora/serialize_cora.py +0 -0
  103. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/imdb/__init__.py +0 -0
  104. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/imdb/imdb_acted_in.parquet.gzip +0 -0
  105. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/imdb/imdb_actors.parquet.gzip +0 -0
  106. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/imdb/imdb_directed_in.parquet.gzip +0 -0
  107. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/imdb/imdb_directors.parquet.gzip +0 -0
  108. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/imdb/imdb_movies_with_genre.parquet.gzip +0 -0
  109. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/imdb/imdb_movies_without_genre.parquet.gzip +0 -0
  110. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/imdb/serialize_imdb.py +0 -0
  111. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/karate/__init__.py +0 -0
  112. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/karate/karate_club.parquet.gzip +0 -0
  113. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/lastfm/__init__.py +0 -0
  114. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/lastfm/artist_nodes.parquet.gzip +0 -0
  115. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/lastfm/serialize_lastfm.py +0 -0
  116. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/lastfm/user_friend_df_directed.parquet.gzip +0 -0
  117. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/lastfm/user_listen_artist_rels.parquet.gzip +0 -0
  118. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/lastfm/user_nodes.parquet.gzip +0 -0
  119. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/resources/lastfm/user_tag_artist_rels.parquet.gzip +0 -0
  120. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/server_version/__init__.py +0 -0
  121. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/server_version/compatible_with.py +0 -0
  122. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/server_version/server_version.py +0 -0
  123. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/session/aura_graph_data_science.py +0 -0
  124. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/session/dbms_connection_info.py +0 -0
  125. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/session/region_suggester.py +0 -0
  126. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/system/__init__.py +0 -0
  127. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/system/config_endpoints.py +0 -0
  128. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/topological_lp/__init__.py +0 -0
  129. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/topological_lp/topological_lp_alpha_runner.py +0 -0
  130. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/topological_lp/topological_lp_endpoints.py +0 -0
  131. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/utils/__init__.py +0 -0
  132. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/utils/util_endpoints.py +0 -0
  133. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience/utils/util_proc_runner.py +0 -0
  134. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience.egg-info/dependency_links.txt +0 -0
  135. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience.egg-info/not-zip-safe +0 -0
  136. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/graphdatascience.egg-info/top_level.txt +0 -0
  137. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/pyproject.toml +0 -0
  138. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/requirements/base/networkx.txt +0 -0
  139. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/requirements/base/ogb.txt +0 -0
  140. {graphdatascience-1.10a1 → graphdatascience-1.11a1}/setup.cfg +0 -0
  141. {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.10a1
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<15.0,>=10.0
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
@@ -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) -> GraphElementPropertyRunner:
383
+ def nodeProperty(self) -> GraphNodePropertyRunner:
383
384
  self._namespace += ".nodeProperty"
384
- return GraphElementPropertyRunner(self._query_runner, self._namespace, self._server_version)
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).rename(columns={"variable": "nodeProperty", "value": "propertyValue"})
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 = self._query_runner.run_cypher(
120
- self._build_query(db_node_properties), {"ids": unique_node_ids}
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(id_vars=["nodeId"]).rename(
127
- columns={"variable": "nodeProperty", "value": "propertyValue"}
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 [NODE_PROPERTY_SCHEMA, RELATIONSHIP_PROPERTY_SCHEMA]:
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 Aura instance.
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
- A flag that indicates that the client should use Apache Arrow
51
- for data streaming if it is available on the server.
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 indicates that, if the flight client is connecting with
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 connecting to 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
- listen_address: str = arrow_info.get("advertisedListenAddress", arrow_info["listenAddress"])
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
- listen_address,
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": "GET_MESSAGE",
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: str = headers.get("Authorization", None)
380
+ auth_header = headers.get("authorization", None)
372
381
  if not auth_header:
373
382
  return
374
- [auth_type, token] = auth_header.split(" ", 1)
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, auto_close=True, bookmarks=bookmarks, config=config, server_version=server_version
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}') YIELD taskName, progress", database=database
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 not progress_percent == "n/a":
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
- self._driver.verify_connectivity()
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"