graphdatascience 1.7a1__tar.gz → 1.9__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 (151) hide show
  1. {graphdatascience-1.7a1 → graphdatascience-1.9}/MANIFEST.in +1 -0
  2. {graphdatascience-1.7a1/graphdatascience.egg-info → graphdatascience-1.9}/PKG-INFO +14 -4
  3. {graphdatascience-1.7a1 → graphdatascience-1.9}/README.md +1 -0
  4. graphdatascience-1.9/graphdatascience/__init__.py +36 -0
  5. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/algo/algo_proc_runner.py +3 -9
  6. graphdatascience-1.9/graphdatascience/algo/single_mode_algo_endpoints.py +18 -0
  7. graphdatascience-1.9/graphdatascience/call_parameters.py +8 -0
  8. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/caller_base.py +5 -1
  9. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/endpoints.py +18 -12
  10. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/error/client_only_endpoint.py +18 -0
  11. graphdatascience-1.9/graphdatascience/error/cypher_warning_handler.py +31 -0
  12. graphdatascience-1.9/graphdatascience/error/gds_not_installed.py +2 -0
  13. graphdatascience-1.9/graphdatascience/gds_session/aura_api.py +236 -0
  14. graphdatascience-1.9/graphdatascience/gds_session/aura_graph_data_science.py +181 -0
  15. graphdatascience-1.9/graphdatascience/gds_session/dbms_connection_info.py +14 -0
  16. graphdatascience-1.9/graphdatascience/gds_session/gds_sessions.py +178 -0
  17. graphdatascience-1.9/graphdatascience/gds_session/schema.py +12 -0
  18. graphdatascience-1.9/graphdatascience/gds_session/session_sizes.py +23 -0
  19. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/graph/graph_alpha_proc_runner.py +11 -12
  20. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/graph/graph_beta_proc_runner.py +12 -15
  21. graphdatascience-1.9/graphdatascience/graph/graph_create_result.py +28 -0
  22. graphdatascience-1.9/graphdatascience/graph/graph_cypher_runner.py +114 -0
  23. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/graph/graph_endpoints.py +0 -7
  24. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/graph/graph_entity_ops_runner.py +95 -76
  25. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/graph/graph_export_runner.py +5 -8
  26. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/graph/graph_object.py +26 -13
  27. graphdatascience-1.9/graphdatascience/graph/graph_proc_runner.py +579 -0
  28. graphdatascience-1.9/graphdatascience/graph/graph_project_runner.py +101 -0
  29. graphdatascience-1.9/graphdatascience/graph/graph_sample_runner.py +70 -0
  30. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/graph_data_science.py +98 -99
  31. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/ignored_server_endpoints.py +5 -2
  32. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/model/graphsage_model.py +8 -5
  33. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/model/link_prediction_model.py +2 -2
  34. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/model/model.py +72 -18
  35. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/model/model_alpha_proc_runner.py +15 -20
  36. graphdatascience-1.9/graphdatascience/model/model_beta_proc_runner.py +31 -0
  37. graphdatascience-1.9/graphdatascience/model/model_proc_runner.py +143 -0
  38. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/model/node_classification_model.py +8 -5
  39. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/model/node_regression_model.py +2 -2
  40. graphdatascience-1.9/graphdatascience/model/simple_rel_embedding_model.py +194 -0
  41. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/pipeline/classification_training_pipeline.py +17 -12
  42. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/pipeline/lp_pipeline_create_runner.py +3 -3
  43. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/pipeline/lp_training_pipeline.py +8 -9
  44. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/pipeline/nc_pipeline_create_runner.py +3 -3
  45. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/pipeline/nc_training_pipeline.py +6 -5
  46. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/pipeline/nr_pipeline_create_runner.py +3 -3
  47. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/pipeline/nr_training_pipeline.py +12 -11
  48. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/pipeline/pipeline_beta_proc_runner.py +4 -22
  49. graphdatascience-1.9/graphdatascience/pipeline/pipeline_proc_runner.py +60 -0
  50. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/pipeline/training_pipeline.py +47 -38
  51. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/query_runner/arrow_graph_constructor.py +11 -1
  52. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/query_runner/arrow_query_runner.py +155 -25
  53. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/query_runner/aura_db_arrow_query_runner.py +81 -34
  54. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/query_runner/cypher_graph_constructor.py +95 -59
  55. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/query_runner/neo4j_query_runner.py +151 -29
  56. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/query_runner/query_runner.py +37 -5
  57. graphdatascience-1.9/graphdatascience/resources/cora/cora_nodes.parquet.gzip +0 -0
  58. graphdatascience-1.9/graphdatascience/resources/cora/cora_rels.parquet.gzip +0 -0
  59. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/resources/cora/serialize_cora.py +4 -9
  60. graphdatascience-1.9/graphdatascience/resources/imdb/imdb_acted_in.parquet.gzip +0 -0
  61. graphdatascience-1.9/graphdatascience/resources/imdb/imdb_actors.parquet.gzip +0 -0
  62. graphdatascience-1.9/graphdatascience/resources/imdb/imdb_directed_in.parquet.gzip +0 -0
  63. graphdatascience-1.9/graphdatascience/resources/imdb/imdb_directors.parquet.gzip +0 -0
  64. graphdatascience-1.9/graphdatascience/resources/imdb/imdb_movies_with_genre.parquet.gzip +0 -0
  65. graphdatascience-1.9/graphdatascience/resources/imdb/imdb_movies_without_genre.parquet.gzip +0 -0
  66. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/resources/imdb/serialize_imdb.py +12 -14
  67. graphdatascience-1.9/graphdatascience/resources/karate/karate_club.parquet.gzip +0 -0
  68. graphdatascience-1.9/graphdatascience/resources/lastfm/artist_nodes.parquet.gzip +0 -0
  69. graphdatascience-1.9/graphdatascience/resources/lastfm/serialize_lastfm.py +119 -0
  70. graphdatascience-1.9/graphdatascience/resources/lastfm/user_friend_df_directed.parquet.gzip +0 -0
  71. graphdatascience-1.9/graphdatascience/resources/lastfm/user_listen_artist_rels.parquet.gzip +0 -0
  72. graphdatascience-1.9/graphdatascience/resources/lastfm/user_nodes.parquet.gzip +0 -0
  73. graphdatascience-1.9/graphdatascience/resources/lastfm/user_tag_artist_rels.parquet.gzip +0 -0
  74. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/server_version/server_version.py +5 -6
  75. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/system/config_endpoints.py +14 -8
  76. graphdatascience-1.9/graphdatascience/system/system_endpoints.py +124 -0
  77. graphdatascience-1.9/graphdatascience/topological_lp/__init__.py +0 -0
  78. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/topological_lp/topological_lp_alpha_runner.py +7 -2
  79. graphdatascience-1.9/graphdatascience/utils/__init__.py +0 -0
  80. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/utils/util_endpoints.py +16 -17
  81. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/utils/util_proc_runner.py +6 -6
  82. graphdatascience-1.9/graphdatascience/version.py +1 -0
  83. {graphdatascience-1.7a1 → graphdatascience-1.9/graphdatascience.egg-info}/PKG-INFO +14 -4
  84. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience.egg-info/SOURCES.txt +29 -14
  85. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience.egg-info/requires.txt +2 -1
  86. {graphdatascience-1.7a1 → graphdatascience-1.9}/requirements/base/base.txt +2 -1
  87. {graphdatascience-1.7a1 → graphdatascience-1.9}/setup.py +2 -3
  88. graphdatascience-1.7a1/graphdatascience/__init__.py +0 -5
  89. graphdatascience-1.7a1/graphdatascience/algo/single_mode_algo_endpoints.py +0 -9
  90. graphdatascience-1.7a1/graphdatascience/error/deprecation_warning.py +0 -29
  91. graphdatascience-1.7a1/graphdatascience/graph/graph_alpha_project_runner.py +0 -16
  92. graphdatascience-1.7a1/graphdatascience/graph/graph_proc_runner.py +0 -420
  93. graphdatascience-1.7a1/graphdatascience/graph/graph_project_runner.py +0 -66
  94. graphdatascience-1.7a1/graphdatascience/graph/graph_sample_runner.py +0 -59
  95. graphdatascience-1.7a1/graphdatascience/model/model_beta_proc_runner.py +0 -37
  96. graphdatascience-1.7a1/graphdatascience/model/model_proc_runner.py +0 -17
  97. graphdatascience-1.7a1/graphdatascience/pipeline/pipeline_proc_runner.py +0 -32
  98. graphdatascience-1.7a1/graphdatascience/resources/cora/cora_nodes_gzip.pkl +0 -0
  99. graphdatascience-1.7a1/graphdatascience/resources/cora/cora_rels_gzip.pkl +0 -0
  100. graphdatascience-1.7a1/graphdatascience/resources/imdb/imdb_acted_in_rels_gzip.pkl +0 -0
  101. graphdatascience-1.7a1/graphdatascience/resources/imdb/imdb_actors_gzip.pkl +0 -0
  102. graphdatascience-1.7a1/graphdatascience/resources/imdb/imdb_directed_in_rels_gzip.pkl +0 -0
  103. graphdatascience-1.7a1/graphdatascience/resources/imdb/imdb_directors_gzip.pkl +0 -0
  104. graphdatascience-1.7a1/graphdatascience/resources/imdb/imdb_movies_with_genre_gzip.pkl +0 -0
  105. graphdatascience-1.7a1/graphdatascience/resources/imdb/imdb_movies_without_genre_gzip.pkl +0 -0
  106. graphdatascience-1.7a1/graphdatascience/resources/imdb/raw/edges.pkl +0 -0
  107. graphdatascience-1.7a1/graphdatascience/resources/imdb/raw/labels.pkl +0 -0
  108. graphdatascience-1.7a1/graphdatascience/resources/imdb/raw/node_features.pkl +0 -0
  109. graphdatascience-1.7a1/graphdatascience/resources/karate/karate_club_gzip.pkl +0 -0
  110. graphdatascience-1.7a1/graphdatascience/system/system_endpoints.py +0 -80
  111. graphdatascience-1.7a1/graphdatascience/version.py +0 -1
  112. {graphdatascience-1.7a1 → graphdatascience-1.9}/LICENSE +0 -0
  113. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/algo/__init__.py +0 -0
  114. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/algo/algo_endpoints.py +0 -0
  115. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/call_builder.py +0 -0
  116. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/error/__init__.py +0 -0
  117. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/error/endpoint_suggester.py +0 -0
  118. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/error/illegal_attr_checker.py +0 -0
  119. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/error/unable_to_connect.py +0 -0
  120. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/error/uncallable_namespace.py +0 -0
  121. {graphdatascience-1.7a1/graphdatascience/graph → graphdatascience-1.9/graphdatascience/gds_session}/__init__.py +0 -0
  122. {graphdatascience-1.7a1/graphdatascience/model → graphdatascience-1.9/graphdatascience/graph}/__init__.py +0 -0
  123. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/graph/graph_type_check.py +0 -0
  124. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/graph/nx_loader.py +0 -0
  125. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/graph/ogb_loader.py +0 -0
  126. {graphdatascience-1.7a1/graphdatascience/pipeline → graphdatascience-1.9/graphdatascience/model}/__init__.py +0 -0
  127. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/model/model_endpoints.py +0 -0
  128. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/model/model_resolver.py +0 -0
  129. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/model/pipeline_model.py +0 -0
  130. {graphdatascience-1.7a1/graphdatascience/query_runner → graphdatascience-1.9/graphdatascience/pipeline}/__init__.py +0 -0
  131. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/pipeline/pipeline_alpha_proc_runner.py +0 -0
  132. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/pipeline/pipeline_endpoints.py +0 -0
  133. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/py.typed +0 -0
  134. {graphdatascience-1.7a1/graphdatascience/resources → graphdatascience-1.9/graphdatascience/query_runner}/__init__.py +0 -0
  135. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/query_runner/graph_constructor.py +0 -0
  136. {graphdatascience-1.7a1/graphdatascience/resources/cora → graphdatascience-1.9/graphdatascience/resources}/__init__.py +0 -0
  137. {graphdatascience-1.7a1/graphdatascience/resources/imdb → graphdatascience-1.9/graphdatascience/resources/cora}/__init__.py +0 -0
  138. {graphdatascience-1.7a1/graphdatascience/resources/karate → graphdatascience-1.9/graphdatascience/resources/imdb}/__init__.py +0 -0
  139. {graphdatascience-1.7a1/graphdatascience/server_version → graphdatascience-1.9/graphdatascience/resources/karate}/__init__.py +0 -0
  140. {graphdatascience-1.7a1/graphdatascience/system → graphdatascience-1.9/graphdatascience/resources/lastfm}/__init__.py +0 -0
  141. {graphdatascience-1.7a1/graphdatascience/topological_lp → graphdatascience-1.9/graphdatascience/server_version}/__init__.py +0 -0
  142. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/server_version/compatible_with.py +0 -0
  143. {graphdatascience-1.7a1/graphdatascience/utils → graphdatascience-1.9/graphdatascience/system}/__init__.py +0 -0
  144. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience/topological_lp/topological_lp_endpoints.py +0 -0
  145. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience.egg-info/dependency_links.txt +0 -0
  146. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience.egg-info/not-zip-safe +0 -0
  147. {graphdatascience-1.7a1 → graphdatascience-1.9}/graphdatascience.egg-info/top_level.txt +0 -0
  148. {graphdatascience-1.7a1 → graphdatascience-1.9}/pyproject.toml +0 -0
  149. {graphdatascience-1.7a1 → graphdatascience-1.9}/requirements/base/networkx.txt +0 -0
  150. {graphdatascience-1.7a1 → graphdatascience-1.9}/requirements/base/ogb.txt +0 -0
  151. {graphdatascience-1.7a1 → graphdatascience-1.9}/setup.cfg +0 -0
@@ -5,3 +5,4 @@ include LICENSE
5
5
  prune graphdatascience/tests
6
6
  prune graphdatascience/resources/cora/serialize_cora.py
7
7
  prune graphdatascience/resources/imdb/serialize_imdb.py
8
+ prune graphdatascience/resources/lastfm/serialize_lastfm.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: graphdatascience
3
- Version: 1.7a1
3
+ Version: 1.9
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
@@ -16,7 +16,6 @@ Classifier: License :: OSI Approved :: Apache Software License
16
16
  Classifier: Operating System :: OS Independent
17
17
  Classifier: Programming Language :: Python :: 3
18
18
  Classifier: Programming Language :: Python :: 3 :: Only
19
- Classifier: Programming Language :: Python :: 3.7
20
19
  Classifier: Programming Language :: Python :: 3.8
21
20
  Classifier: Programming Language :: Python :: 3.9
22
21
  Classifier: Programming Language :: Python :: 3.10
@@ -25,11 +24,21 @@ Classifier: Topic :: Database
25
24
  Classifier: Topic :: Scientific/Engineering
26
25
  Classifier: Topic :: Software Development
27
26
  Classifier: Typing :: Typed
28
- Requires-Python: >=3.7
27
+ Requires-Python: >=3.8
29
28
  Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ Requires-Dist: multimethod<2.0,>=1.0
31
+ Requires-Dist: neo4j<6.0,>=4.4.2
32
+ Requires-Dist: pandas<3.0,>=1.0
33
+ Requires-Dist: pyarrow<15.0,>=10.0
34
+ Requires-Dist: textdistance<5.0,>=4.0
35
+ Requires-Dist: tqdm<5.0,>=4.0
36
+ Requires-Dist: typing-extensions<5.0,>=4.0
37
+ Requires-Dist: requests
30
38
  Provides-Extra: ogb
39
+ Requires-Dist: ogb<2.0,>=1.0; extra == "ogb"
31
40
  Provides-Extra: networkx
32
- License-File: LICENSE
41
+ Requires-Dist: networkx<4.0,>=2.0; extra == "networkx"
33
42
 
34
43
  # Neo4j Graph Data Science Client
35
44
 
@@ -117,6 +126,7 @@ Full end-to-end examples in Jupyter ready-to-run notebooks can be found in the [
117
126
  * [Sampling, Export and Integration with PyG example](examples/import-sample-export-gnn.ipynb)
118
127
  * [Load data to a projected graph via graph construction](examples/load-data-via-graph-construction.ipynb)
119
128
  * [Heterogeneous Node Classification with HashGNN and Autotuning](https://github.com/neo4j/graph-data-science-client/tree/main/examples/heterogeneous-node-classification-with-hashgnn.ipynb)
129
+ * [Perform inference using pre-trained KGE models](examples/kge-predict-transe-pyg-train.ipynb)
120
130
 
121
131
 
122
132
  ## Documentation
@@ -84,6 +84,7 @@ Full end-to-end examples in Jupyter ready-to-run notebooks can be found in the [
84
84
  * [Sampling, Export and Integration with PyG example](examples/import-sample-export-gnn.ipynb)
85
85
  * [Load data to a projected graph via graph construction](examples/load-data-via-graph-construction.ipynb)
86
86
  * [Heterogeneous Node Classification with HashGNN and Autotuning](https://github.com/neo4j/graph-data-science-client/tree/main/examples/heterogeneous-node-classification-with-hashgnn.ipynb)
87
+ * [Perform inference using pre-trained KGE models](examples/kge-predict-transe-pyg-train.ipynb)
87
88
 
88
89
 
89
90
  ## Documentation
@@ -0,0 +1,36 @@
1
+ from .gds_session.gds_sessions import GdsSessions
2
+ from .graph.graph_create_result import GraphCreateResult
3
+ from .graph.graph_object import Graph
4
+ from .graph_data_science import GraphDataScience
5
+ from .model.graphsage_model import GraphSageModel
6
+ from .model.link_prediction_model import LinkFeature, LPModel
7
+ from .model.node_classification_model import NCModel
8
+ from .model.node_regression_model import NRModel
9
+ from .model.pipeline_model import NodePropertyStep
10
+ from .model.simple_rel_embedding_model import SimpleRelEmbeddingModel
11
+ from .pipeline.lp_training_pipeline import LPTrainingPipeline
12
+ from .pipeline.nc_training_pipeline import NCTrainingPipeline
13
+ from .pipeline.nr_training_pipeline import NRTrainingPipeline
14
+ from .query_runner.query_runner import QueryRunner
15
+ from .server_version.server_version import ServerVersion
16
+ from .version import __version__
17
+
18
+ __all__ = [
19
+ "GraphDataScience",
20
+ "GdsSessions",
21
+ "QueryRunner",
22
+ "__version__",
23
+ "ServerVersion",
24
+ "Graph",
25
+ "GraphCreateResult",
26
+ "LPTrainingPipeline",
27
+ "NCTrainingPipeline",
28
+ "NRTrainingPipeline",
29
+ "NodePropertyStep",
30
+ "LinkFeature",
31
+ "LPModel",
32
+ "NCModel",
33
+ "NRModel",
34
+ "GraphSageModel",
35
+ "SimpleRelEmbeddingModel",
36
+ ]
@@ -7,21 +7,15 @@ from ..error.illegal_attr_checker import IllegalAttrChecker
7
7
  from ..graph.graph_object import Graph
8
8
  from ..graph.graph_type_check import graph_type_check
9
9
  from ..model.graphsage_model import GraphSageModel
10
+ from graphdatascience.call_parameters import CallParameters
10
11
 
11
12
 
12
13
  class AlgoProcRunner(IllegalAttrChecker, ABC):
13
14
  @graph_type_check
14
15
  def _run_procedure(self, G: Graph, config: Dict[str, Any], with_logging: bool = True) -> DataFrame:
15
- query = f"CALL {self._namespace}($graph_name, $config)"
16
+ params = CallParameters(graph_name=G.name(), config=config)
16
17
 
17
- params: Dict[str, Any] = {}
18
- params["graph_name"] = G.name()
19
- params["config"] = config
20
-
21
- if with_logging:
22
- return self._query_runner.run_query_with_logging(query, params)
23
- else:
24
- return self._query_runner.run_query(query, params)
18
+ return self._query_runner.call_procedure(endpoint=self._namespace, params=params, logging=with_logging)
25
19
 
26
20
  @graph_type_check
27
21
  def estimate(self, G: Graph, **config: Any) -> "Series[Any]":
@@ -0,0 +1,18 @@
1
+ from ..caller_base import CallerBase
2
+ from ..server_version.compatible_with import compatible_with
3
+ from ..server_version.server_version import ServerVersion
4
+ from .algo_proc_runner import StreamModeRunner
5
+
6
+
7
+ # these algorithms have only one mode
8
+ class SingleModeAlgoEndpoints(CallerBase):
9
+ @property
10
+ @compatible_with("triangles", min_inclusive=ServerVersion(2, 5, 0))
11
+ def triangles(self) -> StreamModeRunner:
12
+ return StreamModeRunner(self._query_runner, f"{self._namespace}.triangles", self._server_version)
13
+
14
+
15
+ class SingleModeAlphaAlgoEndpoints(CallerBase):
16
+ @property
17
+ def triangles(self) -> StreamModeRunner:
18
+ return StreamModeRunner(self._query_runner, f"{self._namespace}.triangles", self._server_version)
@@ -0,0 +1,8 @@
1
+ from typing import Any, OrderedDict
2
+
3
+
4
+ class CallParameters(OrderedDict[str, Any]):
5
+ # since Python 3.6 also initializing through CallParameters(**kwargs) is order preserving
6
+
7
+ def placeholder_str(self) -> str:
8
+ return ", ".join([f"${k}" for k in self.keys()])
@@ -13,7 +13,11 @@ class CallerBase(ABC):
13
13
  self._server_version = server_version
14
14
 
15
15
  def _raise_suggestive_error_message(self, requested_endpoint: str) -> NoReturn:
16
- list_result = self._query_runner.run_query("CALL gds.list() YIELD name", custom_error=False)
16
+ list_result = self._query_runner.call_procedure(
17
+ endpoint="gds.list",
18
+ yields=["name"],
19
+ custom_error=False,
20
+ )
17
21
  all_endpoints = list_result["name"].tolist()
18
22
 
19
23
  raise SyntaxError(generate_suggestive_error_message(requested_endpoint, all_endpoints))
@@ -1,10 +1,9 @@
1
- from .algo.single_mode_algo_endpoints import SingleModeAlgoEndpoints
2
- from .call_builder import IndirectAlphaCallBuilder, IndirectBetaCallBuilder
3
- from .graph.graph_endpoints import (
4
- GraphAlphaEndpoints,
5
- GraphBetaEndpoints,
6
- GraphEndpoints,
1
+ from .algo.single_mode_algo_endpoints import (
2
+ SingleModeAlgoEndpoints,
3
+ SingleModeAlphaAlgoEndpoints,
7
4
  )
5
+ from .call_builder import IndirectAlphaCallBuilder, IndirectBetaCallBuilder
6
+ from .graph.graph_endpoints import GraphAlphaEndpoints, GraphBetaEndpoints
8
7
  from .model.model_endpoints import (
9
8
  ModelAlphaEndpoints,
10
9
  ModelBetaEndpoints,
@@ -17,7 +16,7 @@ from .pipeline.pipeline_endpoints import (
17
16
  )
18
17
  from .query_runner.query_runner import QueryRunner
19
18
  from .server_version.server_version import ServerVersion
20
- from .system.config_endpoints import ConfigEndpoints
19
+ from .system.config_endpoints import AlphaConfigEndpoints, ConfigEndpoints
21
20
  from .system.system_endpoints import (
22
21
  DirectSystemEndpoints,
23
22
  SystemAlphaEndpoints,
@@ -32,14 +31,21 @@ the `gds` namespace. Example of such endpoints are: "graph" and "list".
32
31
  """
33
32
 
34
33
 
35
- class DirectEndpoints(DirectSystemEndpoints, DirectUtilEndpoints, GraphEndpoints, PipelineEndpoints, ModelEndpoints):
34
+ class DirectEndpoints(
35
+ SingleModeAlgoEndpoints,
36
+ DirectSystemEndpoints,
37
+ DirectUtilEndpoints,
38
+ PipelineEndpoints,
39
+ ModelEndpoints,
40
+ ConfigEndpoints,
41
+ ):
36
42
  def __init__(self, query_runner: QueryRunner, namespace: str, server_version: ServerVersion):
37
43
  super().__init__(query_runner, namespace, server_version)
38
44
 
39
45
 
40
46
  """
41
47
  This class should inherit endpoint classes that only expose calls of the `gds.beta` namespace.
42
- Example of such endpoints are: "gds.alpha.model.store" and "gds.alpha.listProgress".
48
+ Example of such endpoints: "gds.alpha.listProgress".
43
49
  """
44
50
 
45
51
 
@@ -48,9 +54,9 @@ class AlphaEndpoints(
48
54
  PipelineAlphaEndpoints,
49
55
  TopologicalLPAlphaEndpoints,
50
56
  ModelAlphaEndpoints,
51
- SingleModeAlgoEndpoints,
57
+ SingleModeAlphaAlgoEndpoints,
52
58
  SystemAlphaEndpoints,
53
- ConfigEndpoints,
59
+ AlphaConfigEndpoints,
54
60
  ):
55
61
  def __init__(self, query_runner: QueryRunner, namespace: str, server_version: ServerVersion):
56
62
  super().__init__(query_runner, namespace, server_version)
@@ -61,7 +67,7 @@ class AlphaEndpoints(
61
67
 
62
68
  """
63
69
  This class should inherit endpoint classes that only expose calls of the `gds.beta` namespace.
64
- Example of such endpoints are: "gds.beta.model.list" and "gds.beta.listProgress".
70
+ Example of such endpoints: "gds.beta.listProgress".
65
71
  """
66
72
 
67
73
 
@@ -1,3 +1,4 @@
1
+ import warnings
1
2
  from functools import wraps
2
3
  from typing import Any, Callable, TypeVar, cast
3
4
 
@@ -23,3 +24,20 @@ def client_only_endpoint(expected_namespace_prefix: str) -> Callable[[F], F]:
23
24
  return cast(F, wrapper)
24
25
 
25
26
  return decorator
27
+
28
+
29
+ def client_deprecated(
30
+ old_endpoint: str,
31
+ new_endpoint: str,
32
+ ) -> Callable[[F], F]:
33
+ def decorator(func: F) -> F:
34
+ wraps(func)
35
+
36
+ @wraps(func)
37
+ def wrapper(self: CallerBase, *args: Any, **kwargs: Any) -> Any:
38
+ warnings.warn(f"Deprecated `{old_endpoint}` in favor of `{new_endpoint}`", DeprecationWarning)
39
+ return func(self, *args, **kwargs)
40
+
41
+ return cast(F, wrapper)
42
+
43
+ return decorator
@@ -0,0 +1,31 @@
1
+ import warnings
2
+ from functools import wraps
3
+ from typing import Any, Callable, TypeVar, cast
4
+
5
+ from ..caller_base import CallerBase
6
+
7
+ F = TypeVar("F", bound=Callable[..., Any])
8
+
9
+
10
+ def filter_id_func_deprecation_warning() -> Callable[[F], F]:
11
+ def decorator(func: F) -> F:
12
+ wraps(func)
13
+
14
+ @wraps(func)
15
+ def wrapper(self: CallerBase, *args: Any, **kwargs: Any) -> Any:
16
+ # GDS uses the numeric id to resolve the node
17
+ warnings.filterwarnings(
18
+ "ignore",
19
+ message=r"^The query used a deprecated function: `id`\.",
20
+ )
21
+
22
+ warnings.filterwarnings(
23
+ "ignore",
24
+ message=r"^The query used a deprecated function. \('id' is no longer supported\)",
25
+ )
26
+
27
+ return func(self, *args, **kwargs)
28
+
29
+ return cast(F, wrapper)
30
+
31
+ return decorator
@@ -0,0 +1,2 @@
1
+ class GdsNotFound(Exception):
2
+ pass
@@ -0,0 +1,236 @@
1
+ from __future__ import annotations
2
+
3
+ import dataclasses
4
+ import logging
5
+ import os
6
+ import time
7
+ from dataclasses import dataclass
8
+ from typing import Any, List, Optional
9
+ from urllib.parse import urlparse
10
+
11
+ import requests as req
12
+ from requests import HTTPError
13
+
14
+ from graphdatascience.version import __version__
15
+
16
+
17
+ @dataclass(repr=True)
18
+ class InstanceDetails:
19
+ id: str
20
+ name: str
21
+ tenant_id: str
22
+ cloud_provider: str
23
+
24
+ @classmethod
25
+ def fromJson(cls, json: dict[str, Any]) -> InstanceDetails:
26
+ return cls(
27
+ id=json["id"],
28
+ name=json["name"],
29
+ tenant_id=json["tenant_id"],
30
+ cloud_provider=json["cloud_provider"],
31
+ )
32
+
33
+
34
+ @dataclass(repr=True)
35
+ class InstanceSpecificDetails(InstanceDetails):
36
+ status: str
37
+ connection_url: str
38
+ memory: str
39
+ type: str
40
+ region: str
41
+
42
+ @classmethod
43
+ def fromJson(cls, json: dict[str, Any]) -> InstanceSpecificDetails:
44
+ return cls(
45
+ id=json["id"],
46
+ name=json["name"],
47
+ tenant_id=json["tenant_id"],
48
+ cloud_provider=json["cloud_provider"],
49
+ status=json["status"],
50
+ connection_url=json.get("connection_url", ""),
51
+ memory=json.get("memory", ""),
52
+ type=json["type"],
53
+ region=json["region"],
54
+ )
55
+
56
+
57
+ @dataclass(repr=True)
58
+ class InstanceCreateDetails:
59
+ id: str
60
+ username: str
61
+ password: str
62
+ connection_url: str
63
+
64
+ @classmethod
65
+ def from_json(cls, json: dict[str, Any]) -> InstanceCreateDetails:
66
+ fields = dataclasses.fields(cls)
67
+ if any(f.name not in json for f in fields):
68
+ raise RuntimeError(f"Missing required field. Expected `{[f.name for f in fields]}` but got `{json}`")
69
+
70
+ return cls(**{f.name: json[f.name] for f in fields})
71
+
72
+
73
+ class AuraApi:
74
+ class AuraAuthToken:
75
+ access_token: str
76
+ expires_in: int
77
+ token_type: str
78
+
79
+ def __init__(self, json: dict[str, Any]) -> None:
80
+ self.access_token = json["access_token"]
81
+ expires_in: int = json["expires_in"]
82
+ self.expires_at = int(time.time()) + expires_in
83
+ self.token_type = json["token_type"]
84
+
85
+ def is_expired(self) -> bool:
86
+ return self.expires_at >= int(time.time())
87
+
88
+ def __init__(self, client_id: str, client_secret: str, tenant_id: Optional[str] = None) -> None:
89
+ self._dev_env = os.environ.get("AURA_ENV")
90
+ self._base_uri = "https://api.neo4j.io" if not self._dev_env else f"https://api-{self._dev_env}.neo4j-dev.io"
91
+ self._credentials = (client_id, client_secret)
92
+ self._token: Optional[AuraApi.AuraAuthToken] = None
93
+ self._logger = logging.getLogger()
94
+ self._tenant_id = tenant_id if tenant_id else self._get_tenant_id()
95
+
96
+ @staticmethod
97
+ def extract_id(uri: str) -> str:
98
+ host = urlparse(uri).hostname
99
+
100
+ if not host:
101
+ raise RuntimeError(f"Could not parse the uri `{uri}`.")
102
+
103
+ return host.split(".")[0].split("-")[0]
104
+
105
+ def create_instance(self, name: str, memory: str, cloud_provider: str, region: str) -> InstanceCreateDetails:
106
+ # TODO should give more control here
107
+ data = {
108
+ "name": name,
109
+ "memory": memory,
110
+ "version": "5",
111
+ "region": region,
112
+ # TODO should be figured out from the tenant details in the future
113
+ "type": self._instance_type(),
114
+ "tenant_id": self._tenant_id,
115
+ "cloud_provider": cloud_provider,
116
+ }
117
+
118
+ response = req.post(
119
+ f"{self._base_uri}/v1/instances",
120
+ json=data,
121
+ headers=self._build_header(),
122
+ )
123
+
124
+ try:
125
+ response.raise_for_status()
126
+ except HTTPError as e:
127
+ print(response.json())
128
+ raise e
129
+
130
+ return InstanceCreateDetails.from_json(response.json()["data"])
131
+
132
+ def delete_instance(self, instance_id: str) -> Optional[InstanceSpecificDetails]:
133
+ response = req.delete(
134
+ f"{self._base_uri}/v1/instances/{instance_id}",
135
+ headers=self._build_header(),
136
+ )
137
+
138
+ if response.status_code == 404:
139
+ return None
140
+
141
+ response.raise_for_status()
142
+
143
+ return InstanceSpecificDetails.fromJson(response.json()["data"])
144
+
145
+ def list_instances(self) -> List[InstanceDetails]:
146
+ response = req.get(
147
+ f"{self._base_uri}/v1/instances",
148
+ headers=self._build_header(),
149
+ params={"tenantId": self._tenant_id},
150
+ )
151
+
152
+ response.raise_for_status()
153
+
154
+ raw_data = response.json()["data"]
155
+
156
+ return [InstanceDetails.fromJson(i) for i in raw_data]
157
+
158
+ def list_instance(self, instance_id: str) -> Optional[InstanceSpecificDetails]:
159
+ response = req.get(
160
+ f"{self._base_uri}/v1/instances/{instance_id}",
161
+ headers=self._build_header(),
162
+ )
163
+
164
+ if response.status_code == 404:
165
+ return None
166
+
167
+ response.raise_for_status()
168
+
169
+ raw_data = response.json()["data"]
170
+
171
+ return InstanceSpecificDetails.fromJson(raw_data)
172
+
173
+ def wait_for_instance_running(
174
+ self, instance_id: str, sleep_time: float = 0.2, max_sleep_time: float = 300
175
+ ) -> Optional[str]:
176
+ waited_time = 0.0
177
+ while waited_time <= max_sleep_time:
178
+ instance = self.list_instance(instance_id)
179
+ if instance is None:
180
+ return "Instance is not found -- please retry"
181
+ elif instance.status in ["deleting", "destroying"]:
182
+ return "Instance is being deleted"
183
+ elif instance.status == "running":
184
+ return None
185
+ else:
186
+ self._logger.debug(
187
+ f"Instance `{instance_id}` is not yet running. "
188
+ f"Current status: {instance.status}. "
189
+ f"Retrying in {sleep_time} seconds..."
190
+ )
191
+ waited_time += sleep_time
192
+ time.sleep(sleep_time)
193
+
194
+ return f"Instance is not running after waiting for {waited_time} seconds"
195
+
196
+ def _get_tenant_id(self) -> str:
197
+ response = req.get(
198
+ f"{self._base_uri}/v1/tenants",
199
+ headers=self._build_header(),
200
+ )
201
+ response.raise_for_status()
202
+
203
+ raw_data = response.json()["data"]
204
+
205
+ if len(raw_data) != 1:
206
+ raise RuntimeError(
207
+ f"This account has access to multiple tenants `{raw_data}`. Please specify which one to use."
208
+ )
209
+
210
+ return raw_data[0]["id"] # type: ignore
211
+
212
+ def _build_header(self) -> dict[str, str]:
213
+ return {"Authorization": f"Bearer {self._auth_token()}", "User-agent": f"neo4j-graphdatascience-v{__version__}"}
214
+
215
+ def _auth_token(self) -> str:
216
+ if self._token is None or self._token.is_expired():
217
+ self._token = self._update_token()
218
+ return self._token.access_token
219
+
220
+ def _update_token(self) -> AuraAuthToken:
221
+ data = {
222
+ "grant_type": "client_credentials",
223
+ }
224
+
225
+ self._logger.debug("Updating oauth token")
226
+
227
+ response = req.post(
228
+ f"{self._base_uri}/oauth/token", data=data, auth=(self._credentials[0], self._credentials[1])
229
+ )
230
+
231
+ response.raise_for_status()
232
+
233
+ return AuraApi.AuraAuthToken(response.json())
234
+
235
+ def _instance_type(self) -> str:
236
+ return "enterprise-ds" if not self._dev_env else "professional-ds"