This is an automated email from the ASF dual-hosted git repository.
jin pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-hugegraph-ai.git
The following commit(s) were added to refs/heads/main by this push:
new 48875c9 feat: initialize hugegraph python client (#5)
48875c9 is described below
commit 48875c9b4755240c5779ac8294c29711b0ee86ef
Author: Simon Cheung <[email protected]>
AuthorDate: Wed Oct 18 12:12:39 2023 +0800
feat: initialize hugegraph python client (#5)
---
LICENSE | 201 +++++++++++++++
hugegraph-python/README.md | 62 +++++
hugegraph-python/example/__init__.py | 16 ++
hugegraph-python/example/client_test.py | 23 ++
hugegraph-python/example/hugegraph_test.py | 48 ++++
hugegraph-python/example/test.py | 68 +++++
hugegraph-python/requirements.txt | 4 +
hugegraph-python/src/__init__.py | 16 ++
hugegraph-python/src/api/__init__.py | 16 ++
hugegraph-python/src/api/common.py | 67 +++++
hugegraph-python/src/api/graph.py | 276 +++++++++++++++++++++
hugegraph-python/src/api/graphs.py | 71 ++++++
hugegraph-python/src/api/gremlin.py | 48 ++++
hugegraph-python/src/api/schema.py | 166 +++++++++++++
hugegraph-python/src/api/schema_manage/__init__.py | 16 ++
.../src/api/schema_manage/edge_label.py | 150 +++++++++++
.../src/api/schema_manage/index_label.py | 103 ++++++++
.../src/api/schema_manage/property_key.py | 168 +++++++++++++
.../src/api/schema_manage/vertex_label.py | 156 ++++++++++++
hugegraph-python/src/client.py | 57 +++++
hugegraph-python/src/structure/__init__.py | 16 ++
hugegraph-python/src/structure/edge_data.py | 64 +++++
hugegraph-python/src/structure/edge_label_data.py | 78 ++++++
hugegraph-python/src/structure/graph_instance.py | 54 ++++
hugegraph-python/src/structure/index_label_data.py | 56 +++++
.../src/structure/property_key_data.py | 51 ++++
hugegraph-python/src/structure/respon_data.py | 39 +++
hugegraph-python/src/structure/vertex_data.py | 44 ++++
.../src/structure/vertex_label_data.py | 62 +++++
hugegraph-python/src/utils/__init__.py | 16 ++
hugegraph-python/src/utils/constants.py | 21 ++
hugegraph-python/src/utils/exceptions.py | 62 +++++
hugegraph-python/src/utils/huge_decorator.py | 45 ++++
hugegraph-python/src/utils/huge_requests.py | 32 +++
hugegraph-python/src/utils/util.py | 43 ++++
35 files changed, 2415 insertions(+)
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8dada3e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/hugegraph-python/README.md b/hugegraph-python/README.md
new file mode 100644
index 0000000..4210647
--- /dev/null
+++ b/hugegraph-python/README.md
@@ -0,0 +1,62 @@
+# hugegraph-python
+A Python SDK for Apache HugeGraph
+
+# Installation
+
+```shell
+pip3 install hugegraph-python
+```
+
+## Install from source
+release soon
+
+# Examples
+
+```python
+from src.client import PyHugeClient
+
+client = PyHugeClient("127.0.0.1", "8080", user="admin", pwd="admin",
graph="hugegraph")
+
+"""system"""
+print(client.get_graphinfo())
+print(client.get_all_graphs())
+print(client.get_version())
+print(client.get_graph_config())
+
+"""schema"""
+schema = client.schema()
+schema.propertyKey("name").asText().ifNotExist().create()
+schema.propertyKey("birthDate").asText().ifNotExist().create()
+schema.vertexLabel("Person").properties("name",
"birthDate").usePrimaryKeyId().primaryKeys(
+ "name").ifNotExist().create()
+schema.vertexLabel("Movie").properties("name").usePrimaryKeyId().primaryKeys("name").ifNotExist().create()
+schema.edgeLabel("ActedIn").sourceLabel("Person").targetLabel("Movie").ifNotExist().create()
+
+print(schema.getVertexLabels())
+print(schema.getEdgeLabels())
+print(schema.getRelations())
+
+"""graph"""
+g = client.graph()
+g.addVertex("Person", {"name": "Al Pacino", "birthDate": "1940-04-25"})
+g.addVertex("Person", {"name": "Robert De Niro", "birthDate": "1943-08-17"})
+g.addVertex("Movie", {"name": "The Godfather"})
+g.addVertex("Movie", {"name": "The Godfather Part II"})
+g.addVertex("Movie", {"name": "The Godfather Coda The Death of Michael
Corleone"})
+
+g.addEdge("ActedIn", "12:Al Pacino", "13:The Godfather", {})
+g.addEdge("ActedIn", "12:Al Pacino", "13:The Godfather Part II", {})
+g.addEdge("ActedIn", "12:Al Pacino", "13:The Godfather Coda The Death of
Michael Corleone", {})
+g.addEdge("ActedIn", "12:Robert De Niro", "13:The Godfather Part II", {})
+
+res = g.getVertexById("12:Al Pacino").label
+# g.removeVertexById("12:Al Pacino")
+print(res)
+g.close()
+
+"""gremlin"""
+g = client.gremlin()
+res = g.exec("g.V().limit(10)")
+print(res)
+
+```
\ No newline at end of file
diff --git a/hugegraph-python/example/__init__.py
b/hugegraph-python/example/__init__.py
new file mode 100644
index 0000000..e0533d9
--- /dev/null
+++ b/hugegraph-python/example/__init__.py
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
diff --git a/hugegraph-python/example/client_test.py
b/hugegraph-python/example/client_test.py
new file mode 100644
index 0000000..c3d9808
--- /dev/null
+++ b/hugegraph-python/example/client_test.py
@@ -0,0 +1,23 @@
+import unittest
+from typing import Any
+from unittest.mock import MagicMock, patch
+
+from example.test_hugegraph import HugeGraph
+
+class HugeGraphTest(unittest.TestCase):
+ def setUp(self) -> None:
+ self.username = "test_user"
+ self.password = "test_password"
+ self.address = "test_address"
+ self.graph = "test_hugegraph"
+ self.port = 1234
+ self.session_pool_size = 10
+
+ @patch("src.client.PyHugeGraph")
+ def test_init(self, mock_graph: Any) -> None:
+ mock_graph.return_value = MagicMock()
+ client = HugeGraph(self.username, self.password, self.address,
self.port, self.graph)
+
+ result = client.exec("g.V().limit(10)")
+ self.assertIsInstance(result, MagicMock)
+
diff --git a/hugegraph-python/example/hugegraph_test.py
b/hugegraph-python/example/hugegraph_test.py
new file mode 100644
index 0000000..e41908a
--- /dev/null
+++ b/hugegraph-python/example/hugegraph_test.py
@@ -0,0 +1,48 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+class HugeGraph:
+ """HugeGraph wrapper for graph operations"""
+
+ def __init__(
+ self,
+ username: str = "default",
+ password: str = "default",
+ address: str = "127.0.0.1",
+ port: int = 8081,
+ graph: str = "hugegraph"
+ ) -> None:
+ """Create a new HugeGraph wrapper instance."""
+ try:
+ from src.client import PyHugeClient
+ except ImportError:
+ raise ValueError(
+ "Please install HugeGraph Python client first: "
+ "`pip3 install hugegraph-python-client`"
+ )
+
+ self.username = username
+ self.password = password
+ self.address = address
+ self.port = port
+ self.graph = graph
+ self.client = PyHugeClient(address, port, user=username, pwd=password,
graph=graph)
+ self.schema = ""
+
+ def exec(self, query) -> str:
+ """Returns the schema of the HugeGraph database"""
+ return self.client.gremlin().exec(query)
diff --git a/hugegraph-python/example/test.py b/hugegraph-python/example/test.py
new file mode 100644
index 0000000..056ccae
--- /dev/null
+++ b/hugegraph-python/example/test.py
@@ -0,0 +1,68 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from src.client import PyHugeClient
+
+if __name__ == '__main__':
+ client = PyHugeClient("127.0.0.1", "8080", user="admin", pwd="admin",
graph="test")
+
+ """schema"""
+ schema = client.schema()
+ schema.propertyKey("name").asText().ifNotExist().create()
+ schema.propertyKey("birthDate").asText().ifNotExist().create()
+ schema.vertexLabel("Person").properties("name",
"birthDate").usePrimaryKeyId().primaryKeys(
+ "name").ifNotExist().create()
+
schema.vertexLabel("Movie").properties("name").usePrimaryKeyId().primaryKeys("name").ifNotExist().create()
+
schema.edgeLabel("ActedIn").sourceLabel("Person").targetLabel("Movie").ifNotExist().create()
+
+ print(schema.getVertexLabels())
+ print(schema.getEdgeLabels())
+ print(schema.getRelations())
+
+ """graph"""
+ g = client.graph()
+ # add Vertex
+ p1 = g.addVertex("Person", {"name": "Al Pacino", "birthDate":
"1940-04-25"})
+ p2 = g.addVertex("Person", {"name": "Robert De Niro", "birthDate":
"1943-08-17"})
+ m1 = g.addVertex("Movie", {"name": "The Godfather"})
+ m2 = g.addVertex("Movie", {"name": "The Godfather Part II"})
+ m3 = g.addVertex("Movie", {"name": "The Godfather Coda The Death of
Michael Corleone"})
+
+ # add Edge
+ g.addEdge("ActedIn", p1.id, m1.id, {})
+ g.addEdge("ActedIn", p1.id, m2.id, {})
+ g.addEdge("ActedIn", p1.id, m3.id, {})
+ g.addEdge("ActedIn", p2.id, m2.id, {})
+
+ # update property
+ g.eliminateVertex("vertex_id", {"property_key": "property_value"})
+
+
+ print(g.getVertexById(p1.id).label)
+ # g.removeVertexById("12:Al Pacino")
+ g.close()
+
+ """gremlin"""
+ g = client.gremlin()
+ print("gremlin.exec: ", g.exec("g.V().limit(10)"))
+
+ """graphs"""
+ g = client.graphs()
+ print("get_graph_info: ", g.get_graph_info())
+ print("get_all_graphs: ", g.get_all_graphs())
+ print("get_version: ", g.get_version())
+ print("get_graph_config: ", g.get_graph_config())
diff --git a/hugegraph-python/requirements.txt
b/hugegraph-python/requirements.txt
new file mode 100644
index 0000000..d9f0102
--- /dev/null
+++ b/hugegraph-python/requirements.txt
@@ -0,0 +1,4 @@
+decorator==5.1.1
+Requests==2.31.0
+setuptools==67.6.1
+urllib3==2.0.3
diff --git a/hugegraph-python/src/__init__.py b/hugegraph-python/src/__init__.py
new file mode 100644
index 0000000..e0533d9
--- /dev/null
+++ b/hugegraph-python/src/__init__.py
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
diff --git a/hugegraph-python/src/api/__init__.py
b/hugegraph-python/src/api/__init__.py
new file mode 100644
index 0000000..e0533d9
--- /dev/null
+++ b/hugegraph-python/src/api/__init__.py
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
diff --git a/hugegraph-python/src/api/common.py
b/hugegraph-python/src/api/common.py
new file mode 100644
index 0000000..42b6c0a
--- /dev/null
+++ b/hugegraph-python/src/api/common.py
@@ -0,0 +1,67 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from src.utils.constants import Constants
+
+
+class ParameterHolder:
+ def __init__(self):
+ self._dic = {}
+
+ def set(self, key, value):
+ self._dic[key] = value
+
+ def get_value(self, key):
+ if key not in self._dic:
+ return None
+ else:
+ return self._dic[key]
+
+ def get_dic(self):
+ return self._dic
+
+ def get_keys(self):
+ return self._dic.keys()
+
+
+class HugeParamsBase:
+ def __init__(self, graph_instance):
+ self._graph_instance = graph_instance
+ self._ip = graph_instance.ip
+ self._port = graph_instance.port
+ self._user = graph_instance.user_name
+ self._pwd = graph_instance.passwd
+ self._host = "http://{}:{}".format(graph_instance.ip,
graph_instance.port)
+ self._auth = (graph_instance.user_name, graph_instance.passwd)
+ self._graph_name = graph_instance.graph_name
+ self._parameter_holder = None
+ self._headers = {
+ 'Content-Type': Constants.HEADER_CONTENT_TYPE
+ }
+ self._timeout = graph_instance.timeout
+
+ def add_parameter(self, key, value):
+ self._parameter_holder.set(key, value)
+ return
+
+ def get_parameter_holder(self):
+ return self._parameter_holder
+
+ def create_parameter_holder(self):
+ self._parameter_holder = ParameterHolder()
+
+ def clean_parameter_holder(self):
+ self._parameter_holder = None
diff --git a/hugegraph-python/src/api/graph.py
b/hugegraph-python/src/api/graph.py
new file mode 100644
index 0000000..1ddb594
--- /dev/null
+++ b/hugegraph-python/src/api/graph.py
@@ -0,0 +1,276 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import json
+
+from src.utils.huge_requests import HugeSession
+from src.api.common import HugeParamsBase
+from src.structure.vertex_data import VertexData
+from src.structure.edge_data import EdgeData
+from src.utils.exceptions import NotFoundError, CreateError, RemoveError,
UpdateError
+from src.utils.util import create_exception, check_if_authorized,
check_if_success
+
+
+class GraphManager(HugeParamsBase):
+ def __init__(self, graph_instance):
+ super().__init__(graph_instance)
+ self.session = self.set_session(HugeSession.new_session())
+
+ def set_session(self, session):
+ self.session = session
+ return session
+
+ def close(self):
+ if self.session:
+ self.session.close()
+
+ def addVertex(self, label, properties, id=None):
+ data = dict()
+ if id is not None:
+ data['id'] = id
+ data['label'] = label
+ data["properties"] = properties
+ url = f'{self._host}/graphs/{self._graph_name}/graph/vertices'
+ response = self.session.post(url, data=json.dumps(data),
auth=self._auth,
+ headers=self._headers,
timeout=self._timeout)
+ if check_if_success(response, CreateError("create vertex failed:
{}".format(response.content))):
+ res = VertexData(json.loads(response.content))
+ return res
+
+ def addVertices(self, input_data):
+ url = f'{self._host}/graphs/{self._graph_name}/graph/vertices/batch'
+
+ data = []
+ for item in input_data:
+ data.append({'label': item[0], 'properties': item[1]})
+ response = self.session.post(url, data=json.dumps(data),
auth=self._auth,
+ headers=self._headers,
timeout=self._timeout)
+ if check_if_success(response, CreateError("create vertexes failed:
{}".format(response.content))):
+ res = []
+ for item in json.loads(response.content):
+ res.append(VertexData({"id": item}))
+ return res
+
+ def appendVertex(self, vertex_id, properties):
+ url =
f'{self._host}/graphs/{self._graph_name}/graph/vertices/"{vertex_id}"?action=append'
+
+ data = {
+ "properties": properties
+ }
+ response = self.session.put(url, data=json.dumps(data),
auth=self._auth,
+ headers=self._headers,
timeout=self._timeout)
+ if check_if_success(response, UpdateError("append vertex failed:
{}".format(response.content))):
+ res = VertexData(json.loads(response.content))
+ return res
+
+ def eliminateVertex(self, vertex_id, properties):
+ url =
f'{self._host}/graphs/{self._graph_name}/graph/vertices/"{vertex_id}"?action=eliminate'
+
+ data = {
+ "properties": properties
+ }
+ response = self.session.put(url, data=json.dumps(data),
auth=self._auth, headers=self._headers,
+ timeout=self._timeout)
+ if check_if_success(response, UpdateError("eliminate vertex failed:
{}".format(response.content))):
+ res = VertexData(json.loads(response.content))
+ return res
+
+ def getVertexById(self, vertex_id):
+ url =
f'{self._host}/graphs/{self._graph_name}/graph/vertices/"{vertex_id}"'
+
+ response = self.session.get(url, auth=self._auth,
headers=self._headers, timeout=self._timeout)
+ if check_if_success(response, NotFoundError("Vertex not found:
{}".format(response.content))):
+ res = VertexData(json.loads(response.content))
+ return res
+
+ def getVertexByPage(self, label, limit, page, properties=None):
+ url = f'{self._host}/graphs/{self._graph_name}/graph/vertices?'
+
+ para = ""
+ para = para + "&label=" + label
+ if properties:
+ para = para + "&properties=" + json.dumps(properties)
+ if page:
+ para += '&page={}'.format(page)
+ else:
+ para += '&page'
+ para = para + "&limit=" + str(limit)
+ url = url + para[1:]
+ response = self.session.get(url, auth=self._auth,
headers=self._headers, timeout=self._timeout)
+ if check_if_success(response, NotFoundError("Vertex not found:
{}".format(response.content))):
+ res = []
+ for item in json.loads(response.content)["vertices"]:
+ res.append(VertexData(item))
+ next_page = json.loads(response.content)["page"]
+ return res, next_page
+
+ def getVertexByCondition(self, label="", limit=0, page='',
properties=None):
+ url = f'{self._host}/graphs/{self._graph_name}/graph/vertices?'
+
+ para = ""
+ if label:
+ para = para + "&label=" + label
+ if properties:
+ para = para + "&properties=" + json.dumps(properties)
+ if limit > 0:
+ para = para + "&limit=" + str(limit)
+ if page:
+ para += '&page={}'.format(page)
+ else:
+ para += '&page'
+ url = url + para[1:]
+ response = self.session.get(url, auth=self._auth,
headers=self._headers, timeout=self._timeout)
+ if check_if_success(response, NotFoundError("Vertex not found:
{}".format(response.content))):
+ res = []
+ for item in json.loads(response.content)["vertices"]:
+ res.append(VertexData(item))
+ return res
+
+ def removeVertexById(self, vertex_id):
+ url =
f'{self._host}/graphs/{self._graph_name}/graph/vertices/"{vertex_id}"'
+ response = self.session.delete(url, auth=self._auth,
headers=self._headers, timeout=self._timeout)
+ if check_if_success(response, RemoveError("remove vertex failed:
{}".format(response.content))):
+ return response.content
+
+ def addEdge(self, edge_label, out_id, in_id, properties):
+ url = f'{self._host}/graphs/{self._graph_name}/graph/edges'
+
+ data = {
+ "label": edge_label,
+ "outV": out_id,
+ "inV": in_id,
+ "properties": properties
+ }
+ response = self.session.post(url, data=json.dumps(data),
auth=self._auth,
+ headers=self._headers,
timeout=self._timeout)
+ if check_if_success(response, CreateError("created edge failed:
{}".format(response.content))):
+ res = EdgeData(json.loads(response.content))
+ return res
+
+ def addEdges(self, input_data):
+ url = f'{self._host}/graphs/{self._graph_name}/graph/edges/batch'
+
+ data = []
+ for item in input_data:
+ data.append({'label': item[0], 'outV': item[1], 'inV': item[2],
'outVLabel': item[3],
+ 'inVLabel': item[4], 'properties': item[5]})
+ response = self.session.post(url, data=json.dumps(data),
auth=self._auth,
+ headers=self._headers,
timeout=self._timeout)
+ if check_if_success(response, CreateError("created edges failed:
{}".format(response.content))):
+ res = []
+ for item in json.loads(response.content):
+ res.append(EdgeData({"id": item}))
+ return res
+
+ def appendEdge(self, edge_id, properties):
+ url =
f'{self._host}/graphs/{self._graph_name}/graph/edges/{edge_id}?action=append'
+
+ data = {
+ "properties": properties
+ }
+ response = self.session.put(url, data=json.dumps(data),
auth=self._auth,
+ headers=self._headers,
timeout=self._timeout)
+ if check_if_success(response, UpdateError("append edge failed:
{}".format(response.content))):
+ res = EdgeData(json.loads(response.content))
+ return res
+
+ def eliminateEdge(self, edge_id, properties):
+ url =
f'{self._host}/graphs/{self._graph_name}/graph/edges/{edge_id}?action=eliminate'
+
+ data = {
+ "properties": properties
+ }
+ response = self.session.put(url, data=json.dumps(data),
auth=self._auth,
+ headers=self._headers,
timeout=self._timeout)
+ if check_if_success(response, UpdateError("eliminate edge failed:
{}".format(response.content))):
+ res = EdgeData(json.loads(response.content))
+ return res
+
+ def getEdgeById(self, edge_id):
+ url = f'{self._host}/graphs/{self._graph_name}/graph/edges/{edge_id}'
+
+ response = self.session.get(url, auth=self._auth,
headers=self._headers, timeout=self._timeout)
+ if check_if_success(response, NotFoundError("not found edge:
{}".format(response.content))):
+ res = EdgeData(json.loads(response.content))
+ return res
+
+ def getEdgeByPage(self, label=None, vertex_id=None, direction=None,
limit=0, page=None, properties=None):
+ url = f'{self._host}/graphs/{self._graph_name}/graph/edges?'
+
+ para = ""
+ if vertex_id:
+ if direction:
+ para = para + "&vertex_id=\"" + vertex_id + "\"&direction=" +
direction
+ else:
+ raise NotFoundError("Direction can not be empty.")
+ if label:
+ para = para + "&label=" + label
+ if properties:
+ para = para + "&properties=" + json.dumps(properties)
+ if page is not None:
+ if page:
+ para += '&page={}'.format(page)
+ else:
+ para += '&page'
+ if limit > 0:
+ para = para + "&limit=" + str(limit)
+ url = url + para[1:]
+ response = self.session.get(url, auth=self._auth,
headers=self._headers, timeout=self._timeout)
+ if check_if_success(response, NotFoundError("not found edges:
{}".format(response.content))):
+ res = []
+ for item in json.loads(response.content)["edges"]:
+ res.append(EdgeData(item))
+ return res, json.loads(response.content)["page"]
+
+ def removeEdgeById(self, edge_id):
+ url = f'{self._host}/graphs/{self._graph_name}/graph/edges/{edge_id}'
+
+ response = self.session.delete(url, auth=self._auth,
headers=self._headers, timeout=self._timeout)
+ if check_if_success(response, RemoveError("remove edge failed:
{}".format(response.content))):
+ return response.content
+
+ def getVerticesById(self, vertex_ids):
+ if not vertex_ids:
+ return []
+ url = f'{self._host}/graphs/{self._graph_name}/traversers/vertices?'
+ for vertex_id in vertex_ids:
+ url += 'ids="{}"&'.format(vertex_id)
+ url = url.rstrip("&")
+ response = self.session.get(url, auth=self._auth,
headers=self._headers, timeout=self._timeout)
+ if response.status_code == 200 and check_if_authorized(response):
+ res = []
+ for item in json.loads(response.content)["vertices"]:
+ res.append(VertexData(item))
+ return res
+ else:
+ create_exception(response.content)
+
+ def getEdgesById(self, edge_ids):
+ if not edge_ids:
+ return []
+ url = f'{self._host}/graphs/{self._graph_name}/traversers/edges?'
+ for vertex_id in edge_ids:
+ url += 'ids={}&'.format(vertex_id)
+ url = url.rstrip("&")
+ response = self.session.get(url, auth=self._auth,
headers=self._headers, timeout=self._timeout)
+ if response.status_code == 200 and check_if_authorized(response):
+ res = []
+ for item in json.loads(response.content)["edges"]:
+ res.append(EdgeData(item))
+ return res
+ else:
+ create_exception(response.content)
diff --git a/hugegraph-python/src/api/graphs.py
b/hugegraph-python/src/api/graphs.py
new file mode 100644
index 0000000..b22ec3a
--- /dev/null
+++ b/hugegraph-python/src/api/graphs.py
@@ -0,0 +1,71 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either expresponses or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+import json
+import re
+
+import requests
+
+from src.api.common import HugeParamsBase
+
+from src.utils.constants import Constants
+from src.utils.exceptions import NotFoundError
+from src.utils.huge_requests import HugeSession
+from src.utils.util import check_if_success
+
+
+class GraphsManager(HugeParamsBase):
+ def __init__(self, graph_instance):
+ super().__init__(graph_instance)
+ self.session = self.set_session(HugeSession.new_session())
+
+ def set_session(self, session):
+ self.session = session
+ return session
+
+ def close(self):
+ if self.session:
+ self.session.close()
+
+ def get_all_graphs(self):
+ url = f'{self._host}/graphs'
+ response = self.session.get(url, auth=self._auth,
headers=self._headers)
+ if check_if_success(response, NotFoundError(response.content)):
+ return str(response.content)
+
+ def get_version(self):
+ url = f'{self._host}/versions'
+ response = self.session.get(url, auth=self._auth,
headers=self._headers)
+ if check_if_success(response, NotFoundError(response.content)):
+ return str(response.content)
+
+ def get_graph_info(self):
+ url = f'{self._host}/graphs/{self._graph_name}'
+ response = self.session.get(url, auth=self._auth,
headers=self._headers)
+ if check_if_success(response, NotFoundError(response.content)):
+ return str(response.content)
+
+ def clear_graph_all_data(self):
+ url =
f'{self._host}/graphs/{self._graph_name}/clear?confirm_message={Constants.CONFORM_MESSAGE}'
+ response = self.session.delete(url, auth=self._auth,
headers=self._headers)
+ if check_if_success(response, NotFoundError(response.content)):
+ return str(response.content)
+
+ def get_graph_config(self):
+ url = self._host + "/graphs" + "/" + self._graph_name + "/conf"
+ response = self.session.get(url, auth=self._auth,
headers=self._headers)
+ if check_if_success(response, NotFoundError(response.content)):
+ return str(response.content)
diff --git a/hugegraph-python/src/api/gremlin.py
b/hugegraph-python/src/api/gremlin.py
new file mode 100644
index 0000000..38a7c30
--- /dev/null
+++ b/hugegraph-python/src/api/gremlin.py
@@ -0,0 +1,48 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+import json
+import re
+
+import requests
+
+from src.api.common import HugeParamsBase
+from src.structure.respon_data import ResponseData
+from src.utils.exceptions import NotFoundError
+from src.utils.huge_requests import HugeSession
+from src.utils.util import check_if_success
+
+
+class GremlinManager(HugeParamsBase):
+ def __init__(self, graph_instance):
+ super().__init__(graph_instance)
+ self.session = self.set_session(HugeSession.new_session())
+
+ def set_session(self, session):
+ self.session = session
+ return session
+
+ def close(self):
+ if self.session:
+ self.session.close()
+
+ def exec(self, gremlin):
+ gremlin = re.sub("^g", self._graph_name + ".traversal()", gremlin)
+ url = f'{self._host}/gremlin?gremlin={gremlin}'
+ response = self.session.get(url, auth=self._auth,
headers=self._headers)
+ error = NotFoundError("Gremlin can't get results:
{}".format(response.content))
+ if check_if_success(response, error):
+ return ResponseData(json.loads(response.content)).result
diff --git a/hugegraph-python/src/api/schema.py
b/hugegraph-python/src/api/schema.py
new file mode 100644
index 0000000..9001028
--- /dev/null
+++ b/hugegraph-python/src/api/schema.py
@@ -0,0 +1,166 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+import json
+
+from src.api.common import HugeParamsBase
+from src.api.schema_manage.edge_label import EdgeLabel
+from src.api.schema_manage.index_label import IndexLabel
+from src.api.schema_manage.property_key import PropertyKey
+from src.api.schema_manage.vertex_label import VertexLabel
+from src.structure.edge_label_data import EdgeLabelData
+from src.structure.index_label_data import IndexLabelData
+from src.structure.property_key_data import PropertyKeyData
+from src.structure.vertex_label_data import VertexLabelData
+from src.utils.exceptions import NotFoundError
+from src.utils.huge_requests import HugeSession
+from src.utils.util import check_if_success
+
+
+class SchemaManager(HugeParamsBase):
+ def __init__(self, graph_instance):
+ super().__init__(graph_instance)
+ self.session = self.set_session(HugeSession.new_session())
+
+ def set_session(self, session):
+ self.session = session
+ return session
+
+ def close(self):
+ if self.session:
+ self.session.close()
+
+ """
+ create schemas, including propertyKey/vertexLabel/edgeLabel/indexLabel
+ """
+
+ def propertyKey(self, property_name):
+ property_key = PropertyKey(self._graph_instance, self.session)
+ property_key.create_parameter_holder()
+ property_key.add_parameter("name", property_name)
+ property_key.add_parameter("not_exist", True)
+ return property_key
+
+ def vertexLabel(self, vertex_name):
+ vertex_label = VertexLabel(self._graph_instance, self.session)
+ vertex_label.create_parameter_holder()
+ vertex_label.add_parameter("name", vertex_name)
+ # vertex_label.add_parameter("id_strategy", "AUTOMATIC")
+ vertex_label.add_parameter("not_exist", True)
+ return vertex_label
+
+ def edgeLabel(self, name):
+ edge_label = EdgeLabel(self._graph_instance, self.session)
+ edge_label.create_parameter_holder()
+ edge_label.add_parameter("name", name)
+ edge_label.add_parameter("not_exist", True)
+ return edge_label
+
+ def indexLabel(self, name):
+ index_label = IndexLabel(self._graph_instance, self.session)
+ index_label.create_parameter_holder()
+ index_label.add_parameter("name", name)
+ return index_label
+
+ """
+ create schemas
+ """
+ def getSchema(self):
+ url = f'{self._host}/graphs/{self._graph_name}/schema'
+ response = self.session.get(url, auth=self._auth,
headers=self._headers)
+ error = NotFoundError(f"schema not found: {response.content}")
+ if check_if_success(response, error):
+ schema = json.loads(response.content)
+ return schema
+
+ def getPropertyKey(self, property_name):
+ url =
f'{self._host}/graphs/{self._graph_name}/schema/propertykeys/{property_name}'
+ response = self.session.get(url, auth=self._auth,
headers=self._headers)
+ error = NotFoundError(f"PropertyKey not found: {response.content}")
+ if check_if_success(response, error):
+ property_keys_data = PropertyKeyData(json.loads(response.content))
+ return property_keys_data
+
+ def getPropertyKeys(self):
+ url = f'{self._host}/graphs/{self._graph_name}/schema/propertykeys'
+ response = self.session.get(url, auth=self._auth,
headers=self._headers)
+ res = []
+ if check_if_success(response):
+ for item in json.loads(response.content)["propertykeys"]:
+ res.append(PropertyKeyData(item))
+ return res
+
+ def getVertexLabel(self, name):
+ url =
f'{self._host}/graphs/{self._graph_name}/schema/vertexlabels/{name}'
+ response = self.session.get(url, auth=self._auth,
headers=self._headers)
+ error = NotFoundError("VertexLabel not found:
{}".format(response.content))
+ if check_if_success(response, error):
+ res = VertexLabelData(json.loads(response.content))
+ return res
+
+ def getVertexLabels(self):
+ url = f'{self._host}/graphs/{self._graph_name}/schema/vertexlabels'
+ response = self.session.get(url, auth=self._auth,
headers=self._headers)
+ res = []
+ if check_if_success(response):
+ for item in json.loads(response.content)["vertexlabels"]:
+ res.append(VertexLabelData(item))
+ return res
+
+ def getEdgeLabel(self, label_name):
+ url =
f'{self._host}/graphs/{self._graph_name}/schema/edgelabels/{label_name}'
+ response = self.session.get(url, auth=self._auth,
headers=self._headers)
+ error = NotFoundError("EdgeLabel not found:
{}".format(response.content))
+ if check_if_success(response, error):
+ res = EdgeLabelData(json.loads(response.content))
+ return res
+
+ def getEdgeLabels(self):
+ url = f'{self._host}/graphs/{self._graph_name}/schema/edgelabels'
+ response = self.session.get(url, auth=self._auth,
headers=self._headers)
+ res = []
+ if check_if_success(response):
+ for item in json.loads(response.content)["edgelabels"]:
+ res.append(EdgeLabelData(item))
+ return res
+
+ def getRelations(self):
+ url = f'{self._host}/graphs/{self._graph_name}/schema/edgelabels'
+ response = self.session.get(url, auth=self._auth,
headers=self._headers)
+ res = []
+ if check_if_success(response):
+ for item in json.loads(response.content)["edgelabels"]:
+ res.append(EdgeLabelData(item).relations())
+ return res
+
+ def getIndexLabel(self, name):
+ url =
f'{self._host}/graphs/{self._graph_name}/schema/indexlabels/{name}'
+ response = self.session.get(url, auth=self._auth,
headers=self._headers)
+ error = NotFoundError("EdgeLabel not found:
{}".format(response.content))
+ if check_if_success(response, error):
+ res = IndexLabelData(json.loads(response.content))
+ return res
+
+ def getIndexLabels(self):
+ url = f'{self._host}/graphs/{self._graph_name}/schema/indexlabels'
+ response = self.session.get(url, auth=self._auth,
headers=self._headers)
+ res = []
+ if check_if_success(response):
+ for item in json.loads(response.content)['indexlabels']:
+ res.append(IndexLabelData(item))
+ return res
diff --git a/hugegraph-python/src/api/schema_manage/__init__.py
b/hugegraph-python/src/api/schema_manage/__init__.py
new file mode 100644
index 0000000..e0533d9
--- /dev/null
+++ b/hugegraph-python/src/api/schema_manage/__init__.py
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
diff --git a/hugegraph-python/src/api/schema_manage/edge_label.py
b/hugegraph-python/src/api/schema_manage/edge_label.py
new file mode 100644
index 0000000..31d81d9
--- /dev/null
+++ b/hugegraph-python/src/api/schema_manage/edge_label.py
@@ -0,0 +1,150 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either expresponses or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import json
+
+from src.api.common import HugeParamsBase
+from src.utils.exceptions import CreateError, UpdateError, RemoveError
+from src.utils.huge_decorator import decorator_params, decorator_create
+from src.utils.util import check_if_success, check_if_authorized
+
+
+class EdgeLabel(HugeParamsBase):
+ def __init__(self, graph_instance, session):
+ super().__init__(graph_instance)
+ self.session = session
+
+ @decorator_params
+ def link(self, source_label, target_label):
+ self._parameter_holder.set("source_label", source_label)
+ self._parameter_holder.set("target_label", target_label)
+ return self
+
+ @decorator_params
+ def sourceLabel(self, source_label):
+ self._parameter_holder.set("source_label", source_label)
+ return self
+
+ @decorator_params
+ def targetLabel(self, target_label):
+ self._parameter_holder.set("target_label", target_label)
+ return self
+
+ @decorator_params
+ def userdata(self, *args):
+ if not self._parameter_holder.get_value("user_data"):
+ self._parameter_holder.set('user_data', dict())
+ user_data = self._parameter_holder.get_value("user_data")
+ i = 0
+ while i < len(args):
+ user_data[args[i]] = args[i + 1]
+ i += 2
+ return self
+
+ @decorator_params
+ def properties(self, *args):
+ self._parameter_holder.set("properties", list(args))
+ return self
+
+ @decorator_params
+ def singleTime(self):
+ self._parameter_holder.set("frequency", "SINGLE")
+ return self
+
+ @decorator_params
+ def multiTimes(self):
+ self._parameter_holder.set("frequency", "MULTIPLE")
+ return self
+
+ @decorator_params
+ def sortKeys(self, *args):
+ self._parameter_holder.set("sort_keys", list(args))
+ return self
+
+ @decorator_params
+ def nullableKeys(self, *args):
+ nullable_keys = set(args)
+ self._parameter_holder.set("nullable_keys", list(nullable_keys))
+ return self
+
+ @decorator_params
+ def ifNotExist(self):
+ url =
f'{self._host}/graphs/{self._graph_name}/schema/edgelabels/{self._parameter_holder.get_value("name")}'
+
+ response = self.session.get(url, auth=self._auth,
headers=self._headers)
+ if response.status_code == 200 and check_if_authorized(response):
+ self._parameter_holder.set("not_exist", False)
+ return self
+
+ @decorator_create
+ def create(self):
+ dic = self._parameter_holder.get_dic()
+ data = dict()
+ keys = ['name', 'source_label', 'target_label', 'nullable_keys',
'properties',
+ 'enable_label_index', 'sort_keys', 'user_data', 'frequency']
+ for key in keys:
+ if key in dic:
+ data[key] = dic[key]
+ url = f'{self._host}/graphs/{self._graph_name}/schema/edgelabels'
+ response = self.session.post(url, data=json.dumps(data),
auth=self._auth, headers=self._headers)
+ self.clean_parameter_holder()
+ error = CreateError('CreateError: "create EdgeLabel failed", Detail:
"{}"'
+ .format(str(response.content)))
+ if check_if_success(response, error):
+ return 'create EdgeLabel success, Detail:
"{}"'.format(str(response.content))
+
+ @decorator_params
+ def remove(self):
+ url =
f'{self._host}/graphs/{self._graph_name}/schema/edgelabels/{self._parameter_holder.get_value("name")}'
+ response = self.session.delete(url, auth=self._auth,
headers=self._headers)
+ self.clean_parameter_holder()
+ error = RemoveError('RemoveError: "remove EdgeLabel failed", Detail:
"{}"'
+ .format(str(response.content)))
+ if check_if_success(response, error):
+ return 'remove EdgeLabel success, Detail:
"{}"'.format(str(response.content))
+
+ @decorator_params
+ def append(self):
+ dic = self._parameter_holder.get_dic()
+ data = dict()
+ keys = ['name', 'nullable_keys', 'properties', 'user_data']
+ for key in keys:
+ if key in dic:
+ data[key] = dic[key]
+
+ url =
f'{self._host}/graphs/{self._graph_name}/schema/edgelabels/{data["name"]}?action=append'
+ response = self.session.put(url, data=json.dumps(data),
auth=self._auth, headers=self._headers)
+ self.clean_parameter_holder()
+ error = UpdateError('UpdateError: "append EdgeLabel failed", Detail:
"{}"'.format(str(response.content)))
+ if check_if_success(response, error):
+ return 'append EdgeLabel success, Detail:
"{}"'.format(str(response.content))
+
+ @decorator_params
+ def eliminate(self):
+ name = self._parameter_holder.get_value("name")
+ user_data = self._parameter_holder.get_value("user_data") if \
+ self._parameter_holder.get_value("user_data") else {}
+ url =
f'{self._host}/graphs/{self._graph_name}/schema/edgelabels/{name}?action=eliminate'
+ data = {
+ "name": name,
+ "user_data": user_data
+ }
+ response = self.session.put(url, data=json.dumps(data),
auth=self._auth, headers=self._headers)
+ self.clean_parameter_holder()
+ error = UpdateError('UpdateError: "eliminate EdgeLabel failed",
Detail: "{}"'.format(str(response.content)))
+ if check_if_success(response, error):
+ return 'eliminate EdgeLabel success, Detail:
"{}"'.format(str(response.content))
diff --git a/hugegraph-python/src/api/schema_manage/index_label.py
b/hugegraph-python/src/api/schema_manage/index_label.py
new file mode 100644
index 0000000..cc93a91
--- /dev/null
+++ b/hugegraph-python/src/api/schema_manage/index_label.py
@@ -0,0 +1,103 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import json
+
+import requests
+
+from src.api.common import HugeParamsBase
+from src.utils.huge_decorator import decorator_params, decorator_create
+from src.utils.exceptions import CreateError, RemoveError
+from src.utils.util import check_if_authorized, check_if_success
+
+
+class IndexLabel(HugeParamsBase):
+ def __init__(self, graph_instance, session):
+ super().__init__(graph_instance)
+ self.session = session
+
+ @decorator_params
+ def onV(self, vertex_label):
+ self._parameter_holder.set("base_value", vertex_label)
+ self._parameter_holder.set("base_type", "VERTEX_LABEL")
+ return self
+
+ @decorator_params
+ def onE(self, edge_label):
+ self._parameter_holder.set("base_value", edge_label)
+ self._parameter_holder.set("base_type", "EDGE_LABEL")
+ return self
+
+ @decorator_params
+ def by(self, *args):
+ if "fields" not in self._parameter_holder.get_keys():
+ self._parameter_holder.set("fields", set())
+ s = self._parameter_holder.get_value("fields")
+ for item in args:
+ s.add(item)
+ return self
+
+ @decorator_params
+ def secondary(self):
+ self._parameter_holder.set("index_type", "SECONDARY")
+ return self
+
+ @decorator_params
+ def range(self):
+ self._parameter_holder.set("index_type", "RANGE")
+ return self
+
+ @decorator_params
+ def Search(self):
+ self._parameter_holder.set("index_type", "SEARCH")
+ return self
+
+ @decorator_params
+ def ifNotExist(self):
+ url =
f'{self._host}/graphs/{self._graph_name}/schema/indexlabels/{self._parameter_holder.get_value("name")}'
+ response = self.session.get(url, auth=self._auth,
headers=self._headers)
+ if response.status_code == 200 and check_if_authorized(response):
+ self._parameter_holder.set("not_exist", False)
+ return self
+
+ @decorator_create
+ def create(self):
+ dic = self._parameter_holder.get_dic()
+ data = dict()
+ data["name"] = dic["name"]
+ data["base_type"] = dic["base_type"]
+ data["base_value"] = dic["base_value"]
+ data["index_type"] = dic["index_type"]
+ data["fields"] = list(dic["fields"])
+ url = f'{self._host}/graphs/{self._graph_name}/schema/indexlabels'
+ response = self.session.post(url, data=json.dumps(data),
auth=self._auth, headers=self._headers)
+ self.clean_parameter_holder()
+ error = CreateError('CreateError: "create IndexLabel failed", '
+ 'Detail "{}"'.format(str(response.content)))
+ if check_if_success(response, error):
+ return 'create IndexLabel success, Deatil:
"{}"'.format(str(response.content))
+
+ @decorator_params
+ def remove(self):
+ name = self._parameter_holder.get_value("name")
+ url =
f'{self._host}/graphs/{self._graph_name}/schema/indexlabels/{name}'
+ response = self.session.delete(url, auth=self._auth,
headers=self._headers)
+ self.clean_parameter_holder()
+ error = RemoveError('RemoveError: "remove IndexLabel failed", '
+ 'Detail "{}"'.format(str(response.content)))
+ if check_if_success(response, error):
+ return 'remove IndexLabel success, Deatil:
"{}"'.format(str(response.content))
diff --git a/hugegraph-python/src/api/schema_manage/property_key.py
b/hugegraph-python/src/api/schema_manage/property_key.py
new file mode 100644
index 0000000..6f9cce4
--- /dev/null
+++ b/hugegraph-python/src/api/schema_manage/property_key.py
@@ -0,0 +1,168 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either expresponses or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import json
+
+import requests
+
+from src.api.common import HugeParamsBase
+from src.utils.exceptions import CreateError, UpdateError, RemoveError
+from src.utils.huge_decorator import decorator_params, decorator_create
+from src.utils.util import check_if_success, check_if_authorized
+
+
+class PropertyKey(HugeParamsBase):
+ def __init__(self, graph_instance, session):
+ super().__init__(graph_instance)
+ self.session = session
+
+ @decorator_params
+ def asInt(self):
+ self._parameter_holder.set("data_type", "INT")
+ return self
+
+ @decorator_params
+ def asText(self):
+ self._parameter_holder.set("data_type", "TEXT")
+ return self
+
+ @decorator_params
+ def asDouble(self):
+ self._parameter_holder.set("data_type", "DOUBLE")
+ return self
+
+ @decorator_params
+ def asDate(self):
+ self._parameter_holder.set("data_type", "DATE")
+ return self
+
+ @decorator_params
+ def valueSingle(self):
+ self._parameter_holder.set("cardinality", "SINGLE")
+ return self
+
+ @decorator_params
+ def valueList(self):
+ self._parameter_holder.set("cardinality", "LIST")
+ return self
+
+ @decorator_params
+ def valueSet(self):
+ self._parameter_holder.set("cardinality", "SET")
+ return self
+
+ @decorator_params
+ def calcMax(self):
+ self._parameter_holder.set("aggregate_type", "MAX")
+ return self
+
+ @decorator_params
+ def calcMin(self):
+ self._parameter_holder.set("aggregate_type", "MIN")
+ return self
+
+ @decorator_params
+ def calcSum(self):
+ self._parameter_holder.set("aggregate_type", "SUM")
+ return self
+
+ @decorator_params
+ def calcOld(self):
+ self._parameter_holder.set("aggregate_type", "OLD")
+ return self
+
+ @decorator_params
+ def userdata(self, *args):
+ user_data = self._parameter_holder.get_value("user_data")
+ if not user_data:
+ self._parameter_holder.set("user_data", dict())
+ user_data = self._parameter_holder.get_value("user_data")
+ i = 0
+ while i < len(args):
+ user_data[args[i]] = args[i + 1]
+ i += 2
+ return self
+
+ def ifNotExist(self):
+ url =
f'{self._host}/graphs/{self._graph_name}/schema/propertykeys/{self._parameter_holder.get_value("name")}'
+ response = self.session.get(url, auth=self._auth,
headers=self._headers)
+ if response.status_code == 200 and check_if_authorized(response):
+ self._parameter_holder.set("not_exist", False)
+ return self
+
+ @decorator_create
+ def create(self):
+ dic = self._parameter_holder.get_dic()
+ property_keys = {
+ "name": dic["name"]
+ }
+ if "data_type" in dic:
+ property_keys["data_type"] = dic["data_type"]
+ if "cardinality" in dic:
+ property_keys["cardinality"] = dic["cardinality"]
+ url = f'{self._host}/graphs/{self._graph_name}/schema/propertykeys'
+ response = self.session.post(url, data=json.dumps(property_keys),
auth=self._auth, headers=self._headers)
+ self.clean_parameter_holder()
+ if check_if_success(response, CreateError(
+ 'CreateError: "create PropertyKey failed", Detail:
{}'.format(response.content))):
+ return 'create PropertyKey success, Detail:
{}'.format(response.content)
+
+ @decorator_params
+ def append(self):
+ property_name = self._parameter_holder.get_value("name")
+ user_data = self._parameter_holder.get_value("user_data")
+ if not user_data:
+ user_data = dict()
+ data = {
+ "name": property_name,
+ "user_data": user_data
+ }
+
+ url =
f'{self._host}/graphs/{self._graph_name}/schema/propertykeys/{property_name}/?action=append'
+ response = self.session.put(url, data=json.dumps(data),
auth=self._auth, headers=self._headers)
+ self.clean_parameter_holder()
+ if check_if_success(response, UpdateError(
+ 'UpdateError: "append PropertyKey failed", Detail:
{}'.format(response.content))):
+ return 'append PropertyKey success, Detail:
{}'.format(response.content)
+
+ @decorator_params
+ def eliminate(self):
+ property_name = self._parameter_holder.get_value("name")
+ user_data = self._parameter_holder.get_value("user_data")
+ if not user_data:
+ user_data = dict()
+ data = {
+ "name": property_name,
+ "user_data": user_data
+ }
+
+ url =
f'{self._host}/graphs/{self._graph_name}/schema/propertykeys/{property_name}/?action=eliminate'
+ response = self.session.put(url, data=json.dumps(data),
auth=self._auth, headers=self._headers)
+ self.clean_parameter_holder()
+ error = UpdateError(f'UpdateError: "eliminate PropertyKey failed",
Detail: {str(response.content)}')
+ if check_if_success(response, error):
+ return 'eliminate PropertyKey success, Detail:
{}'.format(str(response.content))
+
+ @decorator_params
+ def remove(self):
+ dic = self._parameter_holder.get_dic()
+ url =
f'{self._host}/graphs/{self._graph_name}/schema/propertykeys/{dic["name"]}'
+ response = self.session.delete(url)
+ self.clean_parameter_holder()
+ if check_if_success(response, RemoveError(
+ 'RemoveError: "delete PropertyKey failed", Detail:
{}'.format(str(response.content)))):
+ return 'delete PropertyKey success, Detail: {}'.format(dic["name"])
diff --git a/hugegraph-python/src/api/schema_manage/vertex_label.py
b/hugegraph-python/src/api/schema_manage/vertex_label.py
new file mode 100644
index 0000000..462fe13
--- /dev/null
+++ b/hugegraph-python/src/api/schema_manage/vertex_label.py
@@ -0,0 +1,156 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import json
+
+import requests
+
+from src.api.common import HugeParamsBase
+from src.utils.exceptions import CreateError, UpdateError, RemoveError
+from src.utils.huge_decorator import decorator_params, decorator_create
+from src.utils.util import check_if_success, check_if_authorized
+
+
+class VertexLabel(HugeParamsBase):
+ def __init__(self, graph_instance, session):
+ super().__init__(graph_instance)
+ self.session = session
+
+ @decorator_params
+ def useAutomaticId(self):
+ self._parameter_holder.set("id_strategy", "AUTOMATIC")
+ return self
+
+ @decorator_params
+ def useCustomizeStringId(self):
+ self._parameter_holder.set("id_strategy", "CUSTOMIZE_STRING")
+ return self
+
+ @decorator_params
+ def useCustomizeNumberId(self):
+ self._parameter_holder.set("id_strategy", "CUSTOMIZE_NUMBER")
+ return self
+
+ @decorator_params
+ def usePrimaryKeyId(self):
+ self._parameter_holder.set("id_strategy", "PRIMARY_KEY")
+ return self
+
+ @decorator_params
+ def properties(self, *args):
+ self._parameter_holder.set("properties", list(args))
+ return self
+
+ @decorator_params
+ def primaryKeys(self, *args):
+ self._parameter_holder.set("primary_keys", list(args))
+ return self
+
+ @decorator_params
+ def nullableKeys(self, *args):
+ self._parameter_holder.set("nullable_keys", list(args))
+ return self
+
+ @decorator_params
+ def enableLabelIndex(self, flag):
+ self._parameter_holder.set("enable_label_index", flag)
+ return self
+
+ @decorator_params
+ def userdata(self, *args):
+ if "user_data" not in self._parameter_holder.get_keys():
+ self._parameter_holder.set('user_data', dict())
+ user_data = self._parameter_holder.get_value('user_data')
+ i = 0
+ while i < len(args):
+ user_data[args[i]] = args[i + 1]
+ i += 2
+ return self
+
+ def ifNotExist(self):
+ url =
f'{self._host}/graphs/{self._graph_name}/schema/vertexlabels/{self._parameter_holder.get_value("name")}'
+
+ response = self.session.get(url, auth=self._auth,
headers=self._headers)
+ if response.status_code == 200 and check_if_authorized(response):
+ self._parameter_holder.set("not_exist", False)
+ return self
+
+ @decorator_create
+ def create(self):
+ dic = self._parameter_holder.get_dic()
+ key_list = ["name", "id_strategy", "primary_keys", "nullable_keys",
"index_labels",
+ "properties", "enable_label_index", "user_data"]
+ data = {}
+ for key in key_list:
+ if key in dic:
+ data[key] = dic[key]
+ url = f'{self._host}/graphs/{self._graph_name}/schema/vertexlabels'
+ response = self.session.post(url, data=json.dumps(data),
auth=self._auth, headers=self._headers)
+ self.clean_parameter_holder()
+ error = CreateError('CreateError: "create VertexLabel failed", Detail:
"{}"'
+ .format(str(response.content)))
+ if check_if_success(response, error):
+ return 'create VertexLabel success, Detail:
"{}"'.format(str(response.content))
+
+ @decorator_params
+ def append(self):
+ dic = self._parameter_holder.get_dic()
+ properties = dic['properties'] if "properties" in dic else []
+ nullable_keys = dic['nullable_keys'] if "nullable_keys" in dic else []
+ user_data = dic['user_data'] if 'user_data' in dic else {}
+ url =
f'{self._host}/graphs/{self._graph_name}/schema/vertexlabels/{dic["name"]}?action=append'
+
+ data = {
+ "name": dic["name"],
+ "properties": properties,
+ "nullable_keys": nullable_keys,
+ "user_data": user_data
+ }
+ response = self.session.put(url, data=json.dumps(data),
auth=self._auth, headers=self._headers)
+ self.clean_parameter_holder()
+ error = UpdateError('UpdateError: "append VertexLabel failed", Detail:
"{}"'.
+ format(str(response.content)))
+ if check_if_success(response, error):
+ return 'append VertexLabel success, Detail:
"{}"'.format(str(response.content))
+
+ @decorator_params
+ def remove(self):
+ name = self._parameter_holder.get_value("name")
+ url =
f'{self._host}/graphs/{self._graph_name}/schema/vertexlabels/{name}'
+ response = self.session.delete(url, auth=self._auth,
headers=self._headers)
+ self.clean_parameter_holder()
+ error = RemoveError('RemoveError: "remove VertexLabel failed", Detail:
"{}"'.
+ format(str(response.content)))
+ if check_if_success(response, error):
+ return 'remove VertexLabel success, Detail:
"{}"'.format(str(response.content))
+
+ @decorator_params
+ def eliminate(self):
+ name = self._parameter_holder.get_value("name")
+ url =
f'{self._host}/graphs/{self._graph_name}/schema/vertexlabels/{name}/?action=eliminate'
+
+ dic = self._parameter_holder.get_dic()
+ user_data = dic['user_data'] if 'user_data' in dic else {}
+ data = {
+ "name": self._parameter_holder.get_value("name"),
+ "user_data": user_data,
+ }
+ response = self.session.put(url, data=json.dumps(data),
auth=self._auth, headers=self._headers)
+ error = UpdateError('UpdateError: "eliminate VertexLabel failed",
Detail: "{}"'.
+ format(str(response.content)))
+ if check_if_success(response, error):
+ return 'eliminate VertexLabel success, Detail:
"{}"'.format(str(response.content))
diff --git a/hugegraph-python/src/client.py b/hugegraph-python/src/client.py
new file mode 100644
index 0000000..b039725
--- /dev/null
+++ b/hugegraph-python/src/client.py
@@ -0,0 +1,57 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from src.api.common import HugeParamsBase
+from src.api.graph import GraphManager
+from src.api.graphs import GraphsManager
+from src.api.gremlin import GremlinManager
+from src.api.schema import SchemaManager
+from src.structure.graph_instance import GraphInstance
+
+
+class PyHugeClient(HugeParamsBase):
+ def __init__(self, ip, port, graph, user, pwd, timeout=10):
+ self._graph_instance = GraphInstance(ip, port, graph, user, pwd,
timeout)
+ super().__init__(self._graph_instance)
+ self._schema = None
+ self._graph = None
+ self._graphs = None
+ self._gremlin = None
+
+ def schema(self):
+ if self._schema:
+ return self._schema
+ self._schema = SchemaManager(self._graph_instance)
+ return self._schema
+
+ def gremlin(self):
+ if self._gremlin:
+ return self._gremlin
+ self._gremlin = GremlinManager(self._graph_instance)
+ return self._gremlin
+
+ def graph(self):
+ if self._graph:
+ return self._graph
+ self._graph = GraphManager(self._graph_instance)
+ return self._graph
+
+ def graphs(self):
+ if self._graphs:
+ return self._graphs
+ self._graphs = GraphsManager(self._graph_instance)
+ return self._graphs
diff --git a/hugegraph-python/src/structure/__init__.py
b/hugegraph-python/src/structure/__init__.py
new file mode 100644
index 0000000..e0533d9
--- /dev/null
+++ b/hugegraph-python/src/structure/__init__.py
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
diff --git a/hugegraph-python/src/structure/edge_data.py
b/hugegraph-python/src/structure/edge_data.py
new file mode 100644
index 0000000..1269e0a
--- /dev/null
+++ b/hugegraph-python/src/structure/edge_data.py
@@ -0,0 +1,64 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+class EdgeData:
+ def __init__(self, dic):
+ self.__id = dic["id"]
+ self.__label = dic["label"] if "label" in dic else None
+ self.__type = dic["type"] if "type" in dic else None
+ self.__outV = dic["outV"] if "outV" in dic else None
+ self.__outVLabel = dic["outVLabel"] if "outVLabel" in dic else None
+ self.__inV = dic["inV"] if "inV" in dic else None
+ self.__inVLabel = dic["inVLabel"] if "inVLabel" in dic else None
+ self.__properties = dic["properties"] if "properties" in dic else None
+
+ @property
+ def id(self):
+ return self.__id
+
+ @property
+ def label(self):
+ return self.__label
+
+ @property
+ def type(self):
+ return self.__type
+
+ @property
+ def outV(self):
+ return self.__outV
+
+ @property
+ def outVLabel(self):
+ return self.__outVLabel
+
+ @property
+ def inV(self):
+ return self.__inV
+
+ @property
+ def inVLabel(self):
+ return self.__inVLabel
+
+ @property
+ def properties(self):
+ return self.__properties
+
+ def __repr__(self):
+ res = "{}--{}-->{}".format(self.__outV, self.__label, self.__inV)
+ return res
diff --git a/hugegraph-python/src/structure/edge_label_data.py
b/hugegraph-python/src/structure/edge_label_data.py
new file mode 100644
index 0000000..57cfc58
--- /dev/null
+++ b/hugegraph-python/src/structure/edge_label_data.py
@@ -0,0 +1,78 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+class EdgeLabelData:
+ def __init__(self, dic):
+ self.__id = dic["id"]
+ self.__name = dic["name"]
+ self.__source_label = dic["source_label"]
+ self.__target_label = dic["target_label"]
+ self.__frequency = dic["frequency"]
+ self.__sort_keys = dic["sort_keys"]
+ self.__nullable_keys = dic["nullable_keys"]
+ self.__index_labels = dic["index_labels"]
+ self.__properties = dic["properties"]
+ self.__enable_label_index = dic["enable_label_index"]
+ self.__user_data = dic["user_data"]
+
+ @property
+ def id(self):
+ return self.__id
+
+ @property
+ def name(self):
+ return self.__name
+
+ @property
+ def sourceLabel(self):
+ return self.__source_label
+
+ @property
+ def targetLabel(self):
+ return self.__target_label
+
+ @property
+ def frequency(self):
+ return self.__frequency
+
+ @property
+ def sortKeys(self):
+ return self.__sort_keys
+
+ @property
+ def properties(self):
+ return self.__properties
+
+ @property
+ def nullableKeys(self):
+ return self.__nullable_keys
+
+ @property
+ def userdata(self):
+ return self.__user_data
+
+ def relations(self):
+ res = "{}--{}-->{}".format(
+ self.__source_label, self.__name, self.__target_label)
+ return res
+
+ def __repr__(self):
+ res = "name: {}, properties: {}".format(
+ self.__name
+ , self.__properties)
+ return res
diff --git a/hugegraph-python/src/structure/graph_instance.py
b/hugegraph-python/src/structure/graph_instance.py
new file mode 100644
index 0000000..34bed43
--- /dev/null
+++ b/hugegraph-python/src/structure/graph_instance.py
@@ -0,0 +1,54 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+class GraphInstance:
+ def __init__(self, ip, port, graph_name, user_name, passwd, timeout):
+ self.__ip = ip
+ self.__port = port
+ self.__graph_name = graph_name
+ self.__user_name = user_name
+ self.__passwd = passwd
+ self.__timeout = timeout
+
+ @property
+ def ip(self):
+ return self.__ip
+
+ @property
+ def port(self):
+ return self.__port
+
+ @property
+ def graph_name(self):
+ return self.__graph_name
+
+ @property
+ def user_name(self):
+ return self.__user_name
+
+ @property
+ def passwd(self):
+ return self.__passwd
+
+ @property
+ def timeout(self):
+ return self.__timeout
+
+ def __repr__(self):
+ res = f"ip:{self.ip}, port:{self.port}, graph_name:{self.graph_name},
user_name:{self.user_name}, passwd:{self.passwd}, timeout:{self.timeout}"
+ return res
diff --git a/hugegraph-python/src/structure/index_label_data.py
b/hugegraph-python/src/structure/index_label_data.py
new file mode 100644
index 0000000..4f60233
--- /dev/null
+++ b/hugegraph-python/src/structure/index_label_data.py
@@ -0,0 +1,56 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+class IndexLabelData:
+ def __init__(self, dic):
+ self.__id = dic["id"] if "id" in dic else None
+ self.__base_type = dic["base_type"] if "base_type" in dic else None
+ self.__base_value = dic["base_value"] if "base_value" in dic else None
+ self.__name = dic["name"] if "name" in dic else None
+ self.__fields = dic["fields"] if "fields" in dic else None
+ self.__index_type = dic["index_type"] if "index_type" in dic else None
+
+ @property
+ def id(self):
+ return self.__id
+
+ @property
+ def baseType(self):
+ return self.__base_type
+
+ @property
+ def baseValue(self):
+ return self.__base_value
+
+ @property
+ def name(self):
+ return self.__name
+
+ @property
+ def fields(self):
+ return self.__fields
+
+ @property
+ def indexType(self):
+ return self.__index_type
+
+ def __repr__(self):
+ res = "index_name: {}, base_value: {}, base_type: {}, fields: [],
index_type: {}"\
+ .format(self.__name, self.__base_value, self.__base_type,
self.__fields,
+ self.__index_type)
+ return res
diff --git a/hugegraph-python/src/structure/property_key_data.py
b/hugegraph-python/src/structure/property_key_data.py
new file mode 100644
index 0000000..665d632
--- /dev/null
+++ b/hugegraph-python/src/structure/property_key_data.py
@@ -0,0 +1,51 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+class PropertyKeyData:
+ def __init__(self, dic):
+ self.__id = dic["id"]
+ self.__name = dic["name"]
+ self.__cardinality = dic["cardinality"]
+ self.__data_type = dic["data_type"]
+ self.__user_data = dic["user_data"]
+
+ @property
+ def id(self):
+ return self.__id
+
+ @property
+ def cardinality(self):
+ return self.__cardinality
+
+ @property
+ def name(self):
+ return self.__name
+
+ @property
+ def dataType(self):
+ return self.__data_type
+
+ @property
+ def userdata(self):
+ return self.__user_data
+
+ def __repr__(self):
+ res = "name: {}, cardinality: {}, data_type: {}".format(
+ self.__name, self.__cardinality, self.__data_type
+ )
+ return res
diff --git a/hugegraph-python/src/structure/respon_data.py
b/hugegraph-python/src/structure/respon_data.py
new file mode 100644
index 0000000..cbbbc81
--- /dev/null
+++ b/hugegraph-python/src/structure/respon_data.py
@@ -0,0 +1,39 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+class ResponseData:
+ def __init__(self, dic):
+ self.__id = dic["requestId"]
+ self.__status = dic["status"]
+ self.__result = dic["result"]
+
+ @property
+ def id(self):
+ return self.__id
+
+ @property
+ def status(self):
+ return self.__status
+
+ @property
+ def result(self):
+ return self.__result
+
+ def __repr__(self):
+ res = "id: {}, status: {}, result: {}".format(self.__id,
self.__status, self.__result)
+ return res
diff --git a/hugegraph-python/src/structure/vertex_data.py
b/hugegraph-python/src/structure/vertex_data.py
new file mode 100644
index 0000000..eb358bc
--- /dev/null
+++ b/hugegraph-python/src/structure/vertex_data.py
@@ -0,0 +1,44 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+class VertexData:
+ def __init__(self, dic):
+ self.__id = dic["id"]
+ self.__label = dic["label"] if "label" in dic else None
+ self.__type = dic["type"] if "type" in dic else None
+ self.__properties = dic["properties"] if "properties" in dic else None
+
+ @property
+ def id(self):
+ return self.__id
+
+ @property
+ def label(self):
+ return self.__label
+
+ @property
+ def type(self):
+ return self.__type
+
+ @property
+ def properties(self):
+ return self.__properties
+
+ def __repr__(self):
+ res = "id: {}, label: {}, type: {}".format(self.__id, self.__label,
self.__type)
+ return res
diff --git a/hugegraph-python/src/structure/vertex_label_data.py
b/hugegraph-python/src/structure/vertex_label_data.py
new file mode 100644
index 0000000..fe2a8b5
--- /dev/null
+++ b/hugegraph-python/src/structure/vertex_label_data.py
@@ -0,0 +1,62 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+class VertexLabelData:
+ def __init__(self, dic):
+ self.__id = dic["id"]
+ self.__name = dic["name"]
+ self.__id_strategy = dic["id_strategy"]
+ self.__primary_keys = dic["primary_keys"]
+ self.__nullable_keys = dic["nullable_keys"]
+ self.__index_labels = dic["index_labels"]
+ self.__properties = dic["properties"]
+ self.__enable_label_index = dic["enable_label_index"]
+ self.__user_data = dic["user_data"]
+
+ @property
+ def id(self):
+ return self.__id
+
+ @property
+ def name(self):
+ return self.__name
+
+ @property
+ def primaryKeys(self):
+ return self.__primary_keys
+
+ @property
+ def idStrategy(self):
+ return self.__id_strategy
+
+ @property
+ def properties(self):
+ return self.__properties
+
+ @property
+ def nullableKeys(self):
+ return self.__nullable_keys
+
+ @property
+ def userdata(self):
+ return self.__user_data
+
+ def __repr__(self):
+ res = "name: {}, primary_keys: {}, properties: {}".format(
+ self.__name, self.__primary_keys, self.__properties)
+ return res
diff --git a/hugegraph-python/src/utils/__init__.py
b/hugegraph-python/src/utils/__init__.py
new file mode 100644
index 0000000..e0533d9
--- /dev/null
+++ b/hugegraph-python/src/utils/__init__.py
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
diff --git a/hugegraph-python/src/utils/constants.py
b/hugegraph-python/src/utils/constants.py
new file mode 100644
index 0000000..27a5b84
--- /dev/null
+++ b/hugegraph-python/src/utils/constants.py
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+class Constants(str):
+ CONFORM_MESSAGE = "I%27m+sure+to+delete+all+data"
+ HEADER_CONTENT_TYPE = "application/json"
diff --git a/hugegraph-python/src/utils/exceptions.py
b/hugegraph-python/src/utils/exceptions.py
new file mode 100644
index 0000000..7cfb4aa
--- /dev/null
+++ b/hugegraph-python/src/utils/exceptions.py
@@ -0,0 +1,62 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+class NotAuthorizedError(Exception):
+ """
+ Not Authorized
+ """
+
+class InvalidParameter(Exception):
+ """
+ Parameter setting error
+ """
+
+class NotFoundError(Exception):
+ """
+ no content found
+ """
+
+
+class CreateError(Exception):
+ """
+ Failed to create vertex or edge
+ """
+
+
+class RemoveError(Exception):
+ """
+ Failed to delete vertex or edge
+ """
+
+
+class UpdateError(Exception):
+ """
+ Failed to modify node
+ """
+
+
+class DataFormatError(Exception):
+ """
+ Input data format error
+ """
+
+
+class ServiceUnavailableException(Exception):
+ """
+ The server is too busy to be available
+ """
diff --git a/hugegraph-python/src/utils/huge_decorator.py
b/hugegraph-python/src/utils/huge_decorator.py
new file mode 100644
index 0000000..9077bb8
--- /dev/null
+++ b/hugegraph-python/src/utils/huge_decorator.py
@@ -0,0 +1,45 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from decorator import decorator
+
+from src.utils.exceptions import NotAuthorizedError
+
+
+@decorator
+def decorator_params(func, *args, **kwargs):
+ parameter_holder = args[0].get_parameter_holder()
+ if parameter_holder is None or "name" not in parameter_holder.get_keys():
+ print('Parameters required, please set necessary parameters.')
+ raise
+ return func(*args, **kwargs)
+
+
+@decorator
+def decorator_create(func, *args, **kwargs):
+ parameter_holder = args[0].get_parameter_holder()
+ if parameter_holder.get_value('not_exist') is False:
+ return 'Create failed, "{}" already
exists.'.format(parameter_holder.get_value('name'))
+ return func(*args, **kwargs)
+
+
+@decorator
+def decorator_auth(func, *args, **kwargs):
+ response = args[0]
+ if response.status_code == 401:
+ raise NotAuthorizedError("NotAuthorized: {}".format(response.content))
+ return func(*args, **kwargs)
diff --git a/hugegraph-python/src/utils/huge_requests.py
b/hugegraph-python/src/utils/huge_requests.py
new file mode 100644
index 0000000..744e8b5
--- /dev/null
+++ b/hugegraph-python/src/utils/huge_requests.py
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import requests
+from requests.adapters import HTTPAdapter
+from urllib3.util.retry import Retry
+
+
+class HugeSession:
+ @staticmethod
+ def new_session():
+ session = requests.Session()
+ retry = Retry(connect=5, backoff_factor=1)
+ adapter = HTTPAdapter(max_retries=retry)
+ session.mount('http://', adapter)
+ session.mount('https://', adapter)
+ session.keep_alive = False
+ return session
diff --git a/hugegraph-python/src/utils/util.py
b/hugegraph-python/src/utils/util.py
new file mode 100644
index 0000000..9b9424b
--- /dev/null
+++ b/hugegraph-python/src/utils/util.py
@@ -0,0 +1,43 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import json
+
+from src.utils.exceptions import ServiceUnavailableException,
NotAuthorizedError, NotFoundError
+
+
+def create_exception(response_content):
+ data = json.loads(response_content)
+ if "ServiceUnavailableException" in data["exception"]:
+ raise ServiceUnavailableException('ServiceUnavailableException,
"message": "{}", "cause": "{}"'.
+ format(data["message"],
data["cause"]))
+ else:
+ raise Exception(response_content)
+
+
+def check_if_authorized(response):
+ if response.status_code == 401:
+ raise NotAuthorizedError("Please check your username and password.
{}".format(response.content))
+ return True
+
+
+def check_if_success(response, error=None):
+ if (not str(response.status_code).startswith("20")) and
check_if_authorized(response):
+ if error is None:
+ error = NotFoundError(response.content)
+ raise error
+ return True