This is an automated email from the ASF dual-hosted git repository.
jin pushed a commit to branch py-client-new
in repository https://gitbox.apache.org/repos/asf/incubator-hugegraph-ai.git
The following commit(s) were added to refs/heads/py-client-new by this push:
new 5e0c268 feat(client): support graphspace & refactor the request logic
(#61)
5e0c268 is described below
commit 5e0c26883d1a80293ae9838829977270b6cb8d1b
Author: PeiChaoXu <[email protected]>
AuthorDate: Fri Aug 9 11:25:43 2024 +0800
feat(client): support graphspace & refactor the request logic (#61)
Also we keep the compatible with the legacy request url/uri~
This PR introduces significant updates to the hugegraph-python-client
module, focusing on GraphSpace compatibility and API v3 support. Key changes
include:
- [x] Unified connection configuration via HGraphConfig to streamline
parameter management.
- [x] Enhanced HGraphSession for unified HTTP calls with optimized URL
handling.
- [x] Automatic GraphSpace detection based on server API version, ensuring
compatibility with both old and new server versions.
- [x] Refactored HGraphContext and HGraphRouter for more structured URL
definitions using a decorator approach.
- [x] Introduction of the @http decorator for simplified HTTP method and
path definitions.
- [ ] Extensive compatibility testing to ensure a seamless experience
across different server versions.
The update aims to provide a robust and flexible client module for
interacting with HugeGraph servers, catering to the needs of both new and
existing API versions.
---------
Co-authored-by: imbajin <[email protected]>
---
.../src/pyhugegraph/api/auth.py | 233 +++++---------------
.../src/pyhugegraph/api/common.py | 32 +--
.../src/pyhugegraph/api/graph.py | 206 ++++++------------
.../src/pyhugegraph/api/graphs.py | 41 ++--
.../src/pyhugegraph/api/gremlin.py | 33 ++-
.../src/pyhugegraph/api/metric.py | 90 ++------
.../src/pyhugegraph/api/schema.py | 65 +++---
.../pyhugegraph/api/schema_manage/edge_label.py | 58 ++---
.../pyhugegraph/api/schema_manage/index_label.py | 34 ++-
.../pyhugegraph/api/schema_manage/property_key.py | 69 +++---
.../pyhugegraph/api/schema_manage/vertex_label.py | 57 ++---
.../src/pyhugegraph/api/task.py | 37 +---
.../src/pyhugegraph/api/traverser.py | 239 +++++++--------------
.../src/pyhugegraph/api/variable.py | 42 +---
.../src/pyhugegraph/api/version.py | 15 +-
hugegraph-python-client/src/pyhugegraph/client.py | 132 +++++++-----
.../src/pyhugegraph/example/hugegraph_example.py | 18 +-
.../src/pyhugegraph/example/hugegraph_test.py | 4 +-
.../src/pyhugegraph/structure/graph_instance.py | 58 -----
.../src/pyhugegraph/structure/property_key_data.py | 21 +-
.../src/pyhugegraph/utils/huge_config.py | 67 ++++++
.../src/pyhugegraph/utils/huge_decorator.py | 1 +
.../src/pyhugegraph/utils/huge_requests.py | 106 ++++++++-
.../src/pyhugegraph/utils/huge_router.py | 130 +++++++++++
.../src/pyhugegraph/utils/log.py | 75 +++++++
.../src/pyhugegraph/utils/util.py | 12 +-
hugegraph-python-client/src/tests/api/test_auth.py | 8 +-
27 files changed, 887 insertions(+), 996 deletions(-)
diff --git a/hugegraph-python-client/src/pyhugegraph/api/auth.py
b/hugegraph-python-client/src/pyhugegraph/api/auth.py
index 0ce1103..09c80b0 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/auth.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/auth.py
@@ -20,67 +20,42 @@ import json
from pyhugegraph.api.common import HugeParamsBase
from pyhugegraph.utils.exceptions import NotFoundError
-from pyhugegraph.utils.huge_requests import HugeSession
+from pyhugegraph.utils import huge_router as router
from pyhugegraph.utils.util import check_if_success
class AuthManager(HugeParamsBase):
- def __init__(self, graph_instance):
- super().__init__(graph_instance)
- self.__session = HugeSession.new_session()
-
- def close(self):
- if self.__session:
- self.__session.close()
+ @router.http("GET", "auth/users")
def list_users(self, limit=None):
- url = f"{self._host}/graphs/{self._graph_name}/auth/users"
- params = {}
- if limit is not None:
- params["limit"] = limit
- response = self.__session.get(
- url,
- params=params,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ params = {"limit": limit} if limit is not None else {}
+ response = self._invoke_request(params=params)
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return []
+ @router.http("POST", "auth/users")
def create_user(self, user_name, user_password, user_phone=None,
user_email=None):
- url = f"{self._host}/graphs/{self._graph_name}/auth/users"
data = {
"user_name": user_name,
"user_password": user_password,
"user_phone": user_phone,
"user_email": user_email,
}
- response = self.__session.post(
- url,
- data=json.dumps(data),
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("DELETE", "auth/users/{user_id}")
def delete_user(self, user_id):
- url = f"{self._host}/graphs/{self._graph_name}/auth/users/{user_id}"
- response = self.__session.delete(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
if response.status_code != 204:
return response.json()
return {}
+ @router.http("PUT", "auth/users/{user_id}")
def modify_user(
self,
user_id,
@@ -89,275 +64,181 @@ class AuthManager(HugeParamsBase):
user_phone=None,
user_email=None,
):
- url = f"{self._host}/graphs/{self._graph_name}/auth/users/{user_id}"
data = {
"user_name": user_name,
"user_password": user_password,
"user_phone": user_phone,
"user_email": user_email,
}
- response = self.__session.put(
- url,
- data=json.dumps(data),
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "auth/users/{user_id}")
def get_user(self, user_id):
- url = f"{self._host}/graphs/{self._graph_name}/auth/users/{user_id}"
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "auth/groups")
def list_groups(self, limit=None):
- url = f"{self._host}/graphs/{self._graph_name}/auth/groups"
- params = {}
- if limit is not None:
- params["limit"] = limit
- response = self.__session.get(
- url,
- params=params,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ params = {"limit": limit} if limit is not None else {}
+ response = self._invoke_request(params=params)
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return []
+ @router.http("POST", "auth/groups")
def create_group(self, group_name, group_description=None):
- url = f"{self._host}/graphs/{self._graph_name}/auth/groups"
data = {"group_name": group_name, "group_description":
group_description}
- response = self.__session.post(
- url,
- data=json.dumps(data),
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("DELETE", "auth/groups/{group_id}")
def delete_group(self, group_id):
- url = f"{self._host}/graphs/{self._graph_name}/auth/groups/{group_id}"
- response = self.__session.delete(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
if response.status_code != 204:
return response.json()
return {}
+ @router.http("PUT", "auth/groups/{group_id}")
def modify_group(self, group_id, group_name=None, group_description=None):
- url = f"{self._host}/graphs/{self._graph_name}/auth/groups/{group_id}"
data = {"group_name": group_name, "group_description":
group_description}
- response = self.__session.put(
- url,
- data=json.dumps(data),
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "auth/groups/{group_id}")
def get_group(self, group_id):
- url = f"{self._host}/graphs/{self._graph_name}/auth/groups/{group_id}"
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("POST", "auth/accesses")
def grant_accesses(self, group_id, target_id, access_permission):
- url = f"{self._host}/graphs/{self._graph_name}/auth/accesses"
data = {
"group": group_id,
"target": target_id,
"access_permission": access_permission,
}
- response = self.__session.post(
- url,
- data=json.dumps(data),
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("DELETE", "auth/accesses/{access_id}")
def revoke_accesses(self, access_id):
- url =
f"{self._host}/graphs/{self._graph_name}/auth/accesses/{access_id}"
- response = self.__session.delete(
- url, auth=self._auth, headers=self._headers, timeout=self._timeout
- )
+ response = self._invoke_request()
check_if_success(response, NotFoundError(response.content))
+ @router.http("PUT", "auth/accesses/{access_id}")
def modify_accesses(self, access_id, access_description):
- url =
f"{self._host}/graphs/{self._graph_name}/auth/accesses/{access_id}"
# The permission of access can\'t be updated
data = {"access_description": access_description}
- response = self.__session.put(
- url,
- data=json.dumps(data),
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "auth/accesses/{access_id}")
def get_accesses(self, access_id):
- url =
f"{self._host}/graphs/{self._graph_name}/auth/accesses/{access_id}"
- response = self.__session.get(
- url, auth=self._auth, headers=self._headers, timeout=self._timeout
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "auth/accesses")
def list_accesses(self):
- url = f"{self._host}/graphs/{self._graph_name}/auth/accesses"
- response = self.__session.get(
- url, auth=self._auth, headers=self._headers, timeout=self._timeout
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("POST", "auth/targets")
def create_target(self, target_name, target_graph, target_url,
target_resources):
- url = f"{self._host}/graphs/{self._graph_name}/auth/targets"
data = {
"target_name": target_name,
"target_graph": target_graph,
"target_url": target_url,
"target_resources": target_resources,
}
- response = self.__session.post(
- url,
- data=json.dumps(data),
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("DELETE", "auth/targets/{target_id}")
def delete_target(self, target_id):
- url =
f"{self._host}/graphs/{self._graph_name}/auth/targets/{target_id}"
- response = self.__session.delete(
- url, auth=self._auth, headers=self._headers, timeout=self._timeout
- )
+ response = self._invoke_request()
check_if_success(response, NotFoundError(response.content))
- def update_target(self, target_id, target_name, target_graph, target_url,
target_resources):
- url =
f"{self._host}/graphs/{self._graph_name}/auth/targets/{target_id}"
+ @router.http("PUT", "auth/targets/{target_id}")
+ def update_target(
+ self, target_id, target_name, target_graph, target_url,
target_resources
+ ):
data = {
"target_name": target_name,
"target_graph": target_graph,
"target_url": target_url,
"target_resources": target_resources,
}
- response = self.__session.put(
- url,
- data=json.dumps(data),
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
- def get_target(self, target_id):
- url =
f"{self._host}/graphs/{self._graph_name}/auth/targets/{target_id}"
- response = self.__session.get(
- url, auth=self._auth, headers=self._headers, timeout=self._timeout
- )
+ @router.http("GET", "auth/targets/{target_id}")
+ def get_target(self, target_id, response=None):
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "auth/targets")
def list_targets(self):
- url = f"{self._host}/graphs/{self._graph_name}/auth/targets"
- response = self.__session.get(
- url, auth=self._auth, headers=self._headers, timeout=self._timeout
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("POST", "auth/belongs")
def create_belong(self, user_id, group_id):
- url = f"{self._host}/graphs/{self._graph_name}/auth/belongs"
data = {"user": user_id, "group": group_id}
- response = self.__session.post(
- url,
- data=json.dumps(data),
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("DELETE", "auth/belongs/{belong_id}")
def delete_belong(self, belong_id):
- url =
f"{self._host}/graphs/{self._graph_name}/auth/belongs/{belong_id}"
- response = self.__session.delete(
- url, auth=self._auth, headers=self._headers, timeout=self._timeout
- )
+ response = self._invoke_request()
check_if_success(response, NotFoundError(response.content))
+ @router.http("PUT", "auth/belongs/{belong_id}")
def update_belong(self, belong_id, description):
- url =
f"{self._host}/graphs/{self._graph_name}/auth/belongs/{belong_id}"
data = {"belong_description": description}
- response = self.__session.put(
- url,
- data=json.dumps(data),
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "auth/belongs/{belong_id}")
def get_belong(self, belong_id):
- url =
f"{self._host}/graphs/{self._graph_name}/auth/belongs/{belong_id}"
- response = self.__session.get(
- url, auth=self._auth, headers=self._headers, timeout=self._timeout
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "auth/belongs")
def list_belongs(self):
- url = f"{self._host}/graphs/{self._graph_name}/auth/belongs"
- response = self.__session.get(
- url, auth=self._auth, headers=self._headers, timeout=self._timeout
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
diff --git a/hugegraph-python-client/src/pyhugegraph/api/common.py
b/hugegraph-python-client/src/pyhugegraph/api/common.py
index a1dd7d8..731d4d2 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/common.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/common.py
@@ -14,9 +14,14 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-from pyhugegraph.utils.constants import Constants
+from abc import ABC
+from pyhugegraph.utils.huge_router import HGraphRouter
+from pyhugegraph.utils.huge_requests import HGraphSession
+
+
+# todo: rename -> HGraphMetaData or delete
class ParameterHolder:
def __init__(self):
self._dic = {}
@@ -36,19 +41,20 @@ class ParameterHolder:
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 = f"http://{graph_instance.ip}:{graph_instance.port}"
- self._auth = (graph_instance.user_name, graph_instance.passwd)
- self._graph_name = graph_instance.graph_name
+class HGraphContext(ABC):
+ def __init__(self, sess: HGraphSession) -> None:
+ self._sess = sess
+ self._cache = {} # todo: move parameter_holder to cache
+
+ def close(self):
+ self._sess.close()
+
+
+# todo: rename -> HGraphModule | HGraphRouterable | HGraphModel
+class HugeParamsBase(HGraphContext, HGraphRouter):
+ def __init__(self, sess: HGraphSession) -> None:
+ super().__init__(sess)
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)
diff --git a/hugegraph-python-client/src/pyhugegraph/api/graph.py
b/hugegraph-python-client/src/pyhugegraph/api/graph.py
index 959e6b0..708d63c 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/graph.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/graph.py
@@ -17,10 +17,10 @@
import json
-from pyhugegraph.utils.huge_requests import HugeSession
from pyhugegraph.api.common import HugeParamsBase
from pyhugegraph.structure.vertex_data import VertexData
from pyhugegraph.structure.edge_data import EdgeData
+from pyhugegraph.utils import huge_router as router
from pyhugegraph.utils.exceptions import (
NotFoundError,
CreateError,
@@ -35,28 +35,15 @@ from pyhugegraph.utils.util import (
class GraphManager(HugeParamsBase):
- def __init__(self, graph_instance):
- super().__init__(graph_instance)
- self.__session = HugeSession.new_session()
-
- def close(self):
- if self.__session:
- self.__session.close()
+ @router.http("POST", "graph/vertices")
def addVertex(self, label, properties, id=None):
data = {}
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,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(
response, CreateError(f"create vertex failed:
{str(response.content)}")
):
@@ -64,19 +51,12 @@ class GraphManager(HugeParamsBase):
return res
return None
+ @router.http("POST", "graph/vertices/batch")
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,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(
response, CreateError(f"create vertexes failed:
{str(response.content)}")
):
@@ -86,17 +66,10 @@ class GraphManager(HugeParamsBase):
return res
return None
+ @router.http("PUT", 'graph/vertices/"{vertex_id}"?action=append')
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,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(
response, UpdateError(f"append vertex failed:
{str(response.content)}")
):
@@ -104,19 +77,10 @@ class GraphManager(HugeParamsBase):
return res
return None
+ @router.http("PUT", 'graph/vertices/"{vertex_id}"?action=eliminate')
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,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(
response, UpdateError(f"eliminate vertex failed:
{str(response.content)}")
):
@@ -124,20 +88,18 @@ class GraphManager(HugeParamsBase):
return res
return None
+ @router.http("GET", 'graph/vertices/"{vertex_id}"')
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(f"Vertex not found:
{str(response.content)}")):
+ response = self._invoke_request()
+ if check_if_success(
+ response, NotFoundError(f"Vertex not found:
{str(response.content)}")
+ ):
res = VertexData(json.loads(response.content))
return res
return None
def getVertexByPage(self, label, limit, page=None, properties=None):
- url = f"{self._host}/graphs/{self._graph_name}/graph/vertices?"
-
+ path = "graph/vertices?"
para = ""
para = para + "&label=" + label
if properties:
@@ -147,11 +109,11 @@ class GraphManager(HugeParamsBase):
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(f"Vertex not found:
{str(response.content)}")):
+ path = path + para[1:]
+ response = self._sess.request(path)
+ if check_if_success(
+ response, NotFoundError(f"Vertex not found:
{str(response.content)}")
+ ):
res = []
for item in json.loads(response.content)["vertices"]:
res.append(VertexData(item))
@@ -160,8 +122,7 @@ class GraphManager(HugeParamsBase):
return None
def getVertexByCondition(self, label="", limit=0, page=None,
properties=None):
- url = f"{self._host}/graphs/{self._graph_name}/graph/vertices?"
-
+ path = "graph/vertices?"
para = ""
if label:
para = para + "&label=" + label
@@ -173,52 +134,44 @@ class GraphManager(HugeParamsBase):
para += f"&page={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(f"Vertex not found:
{str(response.content)}")):
+ path = path + para[1:]
+ response = self._sess.request(path)
+ if check_if_success(
+ response, NotFoundError(f"Vertex not found:
{str(response.content)}")
+ ):
res = []
for item in json.loads(response.content)["vertices"]:
res.append(VertexData(item))
return res
return None
+ @router.http("DELETE", 'graph/vertices/"{vertex_id}"')
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
- )
+ response = self._invoke_request()
if check_if_success(
response, RemoveError(f"remove vertex failed:
{str(response.content)}")
):
return response.content
return None
+ @router.http("POST", "graph/edges")
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(f"created edge failed:
{str(response.content)}")):
+ response = self._invoke_request(data=json.dumps(data))
+ if check_if_success(
+ response, CreateError(f"created edge failed:
{str(response.content)}")
+ ):
res = EdgeData(json.loads(response.content))
return res
return None
+ @router.http("POST", "graph/edges/batch")
def addEdges(self, input_data):
- url = f"{self._host}/graphs/{self._graph_name}/graph/edges/batch"
-
data = []
for item in input_data:
data.append(
@@ -231,13 +184,7 @@ class GraphManager(HugeParamsBase):
"properties": item[5],
}
)
- response = self.__session.post(
- url,
- data=json.dumps(data),
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(
response, CreateError(f"created edges failed:
{str(response.content)}")
):
@@ -247,33 +194,19 @@ class GraphManager(HugeParamsBase):
return res
return None
+ @router.http("PUT", "graph/edges/{edge_id}?action=append")
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(f"append edge failed:
{str(response.content)}")):
+ response = self._invoke_request(data=json.dumps({"properties":
properties}))
+ if check_if_success(
+ response, UpdateError(f"append edge failed:
{str(response.content)}")
+ ):
res = EdgeData(json.loads(response.content))
return res
return None
+ @router.http("PUT", "graph/edges/{edge_id}?action=eliminate")
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,
- )
+ response = self._invoke_request(data=json.dumps({"properties":
properties}))
if check_if_success(
response, UpdateError(f"eliminate edge failed:
{str(response.content)}")
):
@@ -281,13 +214,12 @@ class GraphManager(HugeParamsBase):
return res
return None
+ @router.http("GET", "graph/edges/{edge_id}")
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(f"not found edge:
{str(response.content)}")):
+ response = self._invoke_request()
+ if check_if_success(
+ response, NotFoundError(f"not found edge: {str(response.content)}")
+ ):
res = EdgeData(json.loads(response.content))
return res
return None
@@ -301,8 +233,7 @@ class GraphManager(HugeParamsBase):
page=None,
properties=None,
):
- url = f"{self._host}/graphs/{self._graph_name}/graph/edges?"
-
+ path = f"graph/edges?"
para = ""
if vertex_id:
if direction:
@@ -319,37 +250,34 @@ class GraphManager(HugeParamsBase):
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(f"not found edges:
{str(response.content)}")):
+ path = path + para[1:]
+ response = self._sess.request(path)
+ if check_if_success(
+ response, NotFoundError(f"not found edges:
{str(response.content)}")
+ ):
res = []
for item in json.loads(response.content)["edges"]:
res.append(EdgeData(item))
return res, json.loads(response.content)["page"]
return None
+ @router.http("DELETE", "graph/edges/{edge_id}")
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(f"remove edge failed:
{str(response.content)}")):
+ response = self._invoke_request()
+ if check_if_success(
+ response, RemoveError(f"remove edge failed:
{str(response.content)}")
+ ):
return response.content
return None
def getVerticesById(self, vertex_ids):
if not vertex_ids:
return []
- url = f"{self._host}/graphs/{self._graph_name}/traversers/vertices?"
+ path = "traversers/vertices?"
for vertex_id in vertex_ids:
- url += f'ids="{vertex_id}"&'
- url = url.rstrip("&")
- response = self.__session.get(
- url, auth=self._auth, headers=self._headers, timeout=self._timeout
- )
+ path += f'ids="{vertex_id}"&'
+ path = path.rstrip("&")
+ response = self._sess.request(path)
if response.status_code == 200 and check_if_authorized(response):
res = []
for item in json.loads(response.content)["vertices"]:
@@ -361,13 +289,11 @@ class GraphManager(HugeParamsBase):
def getEdgesById(self, edge_ids):
if not edge_ids:
return []
- url = f"{self._host}/graphs/{self._graph_name}/traversers/edges?"
+ path = "traversers/edges?"
for vertex_id in edge_ids:
- url += f"ids={vertex_id}&"
- url = url.rstrip("&")
- response = self.__session.get(
- url, auth=self._auth, headers=self._headers, timeout=self._timeout
- )
+ path += f"ids={vertex_id}&"
+ path = path.rstrip("&")
+ response = self._sess.request(path)
if response.status_code == 200 and check_if_authorized(response):
res = []
for item in json.loads(response.content)["edges"]:
diff --git a/hugegraph-python-client/src/pyhugegraph/api/graphs.py
b/hugegraph-python-client/src/pyhugegraph/api/graphs.py
index 8212a90..c7f4e30 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/graphs.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/graphs.py
@@ -15,58 +15,53 @@
# specific language governing permissions and limitations
# under the License.
+import json
from pyhugegraph.api.common import HugeParamsBase
-
-from pyhugegraph.utils.constants import Constants
+from pyhugegraph.utils import huge_router as router
from pyhugegraph.utils.exceptions import NotFoundError
-from pyhugegraph.utils.huge_requests import HugeSession
from pyhugegraph.utils.util import check_if_success
class GraphsManager(HugeParamsBase):
- def __init__(self, graph_instance):
- super().__init__(graph_instance)
- self.__session = HugeSession.new_session()
-
- def close(self):
- if self.__session:
- self.__session.close()
+ @router.http("GET", "/graphs")
def get_all_graphs(self):
- url = f"{self._host}/graphs"
- response = self.__session.get(url, auth=self._auth,
headers=self._headers)
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return str(response.content)
return ""
+ @router.http("GET", "/versions")
def get_version(self):
- url = f"{self._host}/versions"
- response = self.__session.get(url, auth=self._auth,
headers=self._headers)
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return str(response.content)
return ""
+ @router.http("GET", "")
def get_graph_info(self):
- url = f"{self._host}/graphs/{self._graph_name}"
- response = self.__session.get(url, auth=self._auth,
headers=self._headers)
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return str(response.content)
return ""
def clear_graph_all_data(self):
- url = (
- f"{self._host}/graphs/{self._graph_name}/clear?confirm_message="
- f"{Constants.CONFORM_MESSAGE}"
- )
- response = self.__session.delete(url, auth=self._auth,
headers=self._headers)
+ if self._sess._cfg.gs_supported:
+ response = self._sess.request(
+ "", "PUT", data=json.dumps({"action": "clear", "clear_schema":
True})
+ )
+ else:
+ response = self._sess.request(
+ "clear?confirm_message=I%27m+sure+to+delete+all+data", "DELETE"
+ )
if check_if_success(response, NotFoundError(response.content)):
return str(response.content)
return ""
+ @router.http("GET", "conf")
def get_graph_config(self):
- url = self._host + "/graphs" + "/" + self._graph_name + "/conf"
- response = self.__session.get(url, auth=self._auth,
headers=self._headers)
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return str(response.content)
return ""
diff --git a/hugegraph-python-client/src/pyhugegraph/api/gremlin.py
b/hugegraph-python-client/src/pyhugegraph/api/gremlin.py
index 5726075..3095642 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/gremlin.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/gremlin.py
@@ -21,33 +21,26 @@ from pyhugegraph.api.common import HugeParamsBase
from pyhugegraph.structure.gremlin_data import GremlinData
from pyhugegraph.structure.response_data import ResponseData
from pyhugegraph.utils.exceptions import NotFoundError
-from pyhugegraph.utils.huge_requests import HugeSession
+from pyhugegraph.utils import huge_router as router
from pyhugegraph.utils.util import check_if_success
class GremlinManager(HugeParamsBase):
- def __init__(self, graph_instance):
- super().__init__(graph_instance)
- self.__session = HugeSession.new_session()
-
- def close(self):
- if self.__session:
- self.__session.close()
+ @router.http("POST", "/gremlin")
def exec(self, gremlin):
- url = f"{self._host}/gremlin"
gremlin_data = GremlinData(gremlin)
- gremlin_data.aliases = {
- "graph": self._graph_name,
- "g": "__g_" + self._graph_name,
- }
- response = self.__session.post(
- url,
- data=gremlin_data.to_json(),
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ if self._sess._cfg.gs_supported:
+ gremlin_data.aliases = {
+ "graph":
f"{self._sess._cfg.graphspace}-{self._sess._cfg.graph_name}",
+ "g":
f"__g_{self._sess._cfg.graphspace}-{self._sess._cfg.graph_name}",
+ }
+ else:
+ gremlin_data.aliases = {
+ "graph": f"{self._sess._cfg.graph_name}",
+ "g": f"__g_{self._sess._cfg.graph_name}",
+ }
+ response = self._invoke_request(data=gremlin_data.to_json())
error = NotFoundError(f"Gremlin can't get results:
{str(response.content)}")
if check_if_success(response, error):
return ResponseData(json.loads(response.content)).result
diff --git a/hugegraph-python-client/src/pyhugegraph/api/metric.py
b/hugegraph-python-client/src/pyhugegraph/api/metric.py
index 51be7b4..9d27d52 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/metric.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/metric.py
@@ -17,123 +17,71 @@
from pyhugegraph.api.common import HugeParamsBase
from pyhugegraph.utils.exceptions import NotFoundError
-from pyhugegraph.utils.huge_requests import HugeSession
+from pyhugegraph.utils import huge_router as router
from pyhugegraph.utils.util import check_if_success
class MetricsManager(HugeParamsBase):
- def __init__(self, graph_instance):
- super().__init__(graph_instance)
- self.__session = HugeSession.new_session()
-
- def close(self):
- if self.__session:
- self.__session.close()
+ @router.http("GET", "/metrics/?type=json")
def get_all_basic_metrics(self):
- url = f"{self._host}/metrics/?type=json"
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "/metrics/gauges")
def get_gauges_metrics(self):
- url = f"{self._host}/metrics/gauges"
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "/metrics/counters")
def get_counters_metrics(self):
- url = f"{self._host}/metrics/counters"
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "/metrics/gauges")
def get_histograms_metrics(self):
- url = f"{self._host}/metrics/histograms"
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "/metrics/meters")
def get_meters_metrics(self):
- url = f"{self._host}/metrics/meters"
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "/metrics/timers")
def get_timers_metrics(self):
- url = f"{self._host}/metrics/timers"
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "/metrics/statistics/?type=json")
def get_statistics_metrics(self):
- url = f"{self._host}/metrics/statistics/?type=json"
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "/metrics/system")
def get_system_metrics(self):
- url = f"{self._host}/metrics/system"
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "/metrics/backend")
def get_backend_metrics(self):
- url = f"{self._host}/metrics/backend"
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
diff --git a/hugegraph-python-client/src/pyhugegraph/api/schema.py
b/hugegraph-python-client/src/pyhugegraph/api/schema.py
index 2818c5b..ab92bc8 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/schema.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/schema.py
@@ -18,6 +18,7 @@
import json
+from typing import Optional, Dict
from pyhugegraph.api.common import HugeParamsBase
from pyhugegraph.api.schema_manage.edge_label import EdgeLabel
from pyhugegraph.api.schema_manage.index_label import IndexLabel
@@ -28,32 +29,24 @@ from pyhugegraph.structure.index_label_data import
IndexLabelData
from pyhugegraph.structure.property_key_data import PropertyKeyData
from pyhugegraph.structure.vertex_label_data import VertexLabelData
from pyhugegraph.utils.exceptions import NotFoundError
-from pyhugegraph.utils.huge_requests import HugeSession
from pyhugegraph.utils.util import check_if_success
+from pyhugegraph.utils import huge_router as router
class SchemaManager(HugeParamsBase):
- def __init__(self, graph_instance):
- super().__init__(graph_instance)
- self.__session = HugeSession.new_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)
+ def propertyKey(self, property_name) -> PropertyKey:
+ property_key = PropertyKey(self._sess)
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 = VertexLabel(self._sess)
vertex_label.create_parameter_holder()
vertex_label.add_parameter("name", vertex_name)
# vertex_label.add_parameter("id_strategy", "AUTOMATIC")
@@ -61,39 +54,39 @@ class SchemaManager(HugeParamsBase):
return vertex_label
def edgeLabel(self, name):
- edge_label = EdgeLabel(self._graph_instance, self.__session)
+ edge_label = EdgeLabel(self._sess)
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 = IndexLabel(self._sess)
index_label.create_parameter_holder()
index_label.add_parameter("name", name)
return index_label
- def getSchema(self):
- url = f"{self._host}/graphs/{self._graph_name}/schema"
- response = self.__session.get(url, auth=self._auth,
headers=self._headers)
+ @router.http("GET", "schema?format={format}")
+ def getSchema(self, format: str = "json") -> Optional[Dict]:
+ response = self._invoke_request()
error = NotFoundError(f"schema not found: {str(response.content)}")
if check_if_success(response, error):
schema = json.loads(response.content)
return schema
return None
+ @router.http("GET", "schema/propertykeys/{property_name}")
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)
+ response = self._invoke_request()
error = NotFoundError(f"PropertyKey not found:
{str(response.content)}")
if check_if_success(response, error):
property_keys_data = PropertyKeyData(json.loads(response.content))
return property_keys_data
return None
+ @router.http("GET", "schema/propertykeys")
def getPropertyKeys(self):
- url = f"{self._host}/graphs/{self._graph_name}/schema/propertykeys"
- response = self.__session.get(url, auth=self._auth,
headers=self._headers)
+ response = self._invoke_request()
res = []
if check_if_success(response):
for item in json.loads(response.content)["propertykeys"]:
@@ -101,63 +94,63 @@ class SchemaManager(HugeParamsBase):
return res
return None
+ @router.http("GET", "schema/vertexlabels/{name}")
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)
+ response = self._invoke_request()
error = NotFoundError(f"VertexLabel not found:
{str(response.content)}")
if check_if_success(response, error):
res = VertexLabelData(json.loads(response.content))
return res
return None
+ @router.http("GET", "schema/vertexlabels")
def getVertexLabels(self):
- url = f"{self._host}/graphs/{self._graph_name}/schema/vertexlabels"
- response = self.__session.get(url, auth=self._auth,
headers=self._headers)
+ response = self._invoke_request()
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)
+ @router.http("GET", "schema/edgelabels/{label_name}")
+ def getEdgeLabel(self, label_name: str):
+ response = self._invoke_request()
error = NotFoundError(f"EdgeLabel not found: {str(response.content)}")
if check_if_success(response, error):
res = EdgeLabelData(json.loads(response.content))
return res
return None
+ @router.http("GET", "schema/edgelabels")
def getEdgeLabels(self):
- url = f"{self._host}/graphs/{self._graph_name}/schema/edgelabels"
- response = self.__session.get(url, auth=self._auth,
headers=self._headers)
+ response = self._invoke_request()
res = []
if check_if_success(response):
for item in json.loads(response.content)["edgelabels"]:
res.append(EdgeLabelData(item))
return res
+ @router.http("GET", "schema/edgelabels")
def getRelations(self):
- url = f"{self._host}/graphs/{self._graph_name}/schema/edgelabels"
- response = self.__session.get(url, auth=self._auth,
headers=self._headers)
+ response = self._invoke_request()
res = []
if check_if_success(response):
for item in json.loads(response.content)["edgelabels"]:
res.append(EdgeLabelData(item).relations())
return res
+ @router.http("GET", "schema/indexlabels/{name}")
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)
+ response = self._invoke_request()
error = NotFoundError(f"EdgeLabel not found: {str(response.content)}")
if check_if_success(response, error):
res = IndexLabelData(json.loads(response.content))
return res
return None
+ @router.http("GET", "schema/indexlabels")
def getIndexLabels(self):
- url = f"{self._host}/graphs/{self._graph_name}/schema/indexlabels"
- response = self.__session.get(url, auth=self._auth,
headers=self._headers)
+ response = self._invoke_request()
res = []
if check_if_success(response):
for item in json.loads(response.content)["indexlabels"]:
diff --git
a/hugegraph-python-client/src/pyhugegraph/api/schema_manage/edge_label.py
b/hugegraph-python-client/src/pyhugegraph/api/schema_manage/edge_label.py
index f694a49..ee6b8c1 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/schema_manage/edge_label.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/schema_manage/edge_label.py
@@ -24,28 +24,25 @@ from pyhugegraph.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):
+ def link(self, source_label, target_label) -> "EdgeLabel":
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):
+ def sourceLabel(self, source_label) -> "EdgeLabel":
self._parameter_holder.set("source_label", source_label)
return self
@decorator_params
- def targetLabel(self, target_label):
+ def targetLabel(self, target_label) -> "EdgeLabel":
self._parameter_holder.set("target_label", target_label)
return self
@decorator_params
- def userdata(self, *args):
+ def userdata(self, *args) -> "EdgeLabel":
if not self._parameter_holder.get_value("user_data"):
self._parameter_holder.set("user_data", {})
user_data = self._parameter_holder.get_value("user_data")
@@ -56,39 +53,35 @@ class EdgeLabel(HugeParamsBase):
return self
@decorator_params
- def properties(self, *args):
+ def properties(self, *args) -> "EdgeLabel":
self._parameter_holder.set("properties", list(args))
return self
@decorator_params
- def singleTime(self):
+ def singleTime(self) -> "EdgeLabel":
self._parameter_holder.set("frequency", "SINGLE")
return self
@decorator_params
- def multiTimes(self):
+ def multiTimes(self) -> "EdgeLabel":
self._parameter_holder.set("frequency", "MULTIPLE")
return self
@decorator_params
- def sortKeys(self, *args):
+ def sortKeys(self, *args) -> "EdgeLabel":
self._parameter_holder.set("sort_keys", list(args))
return self
@decorator_params
- def nullableKeys(self, *args):
+ def nullableKeys(self, *args) -> "EdgeLabel":
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}"
- f'/schema/edgelabels/{self._parameter_holder.get_value("name")}'
- )
-
- response = self.__session.get(url, auth=self._auth,
headers=self._headers)
+ def ifNotExist(self) -> "EdgeLabel":
+ path = f'schema/edgelabels/{self._parameter_holder.get_value("name")}'
+ response = self._sess.request(path)
if response.status_code == 200 and check_if_authorized(response):
self._parameter_holder.set("not_exist", False)
return self
@@ -111,10 +104,8 @@ class EdgeLabel(HugeParamsBase):
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
- )
+ path = "schema/edgelabels"
+ response = self._sess.request(path, "POST", data=json.dumps(data))
self.clean_parameter_holder()
error = CreateError(
f'CreateError: "create EdgeLabel failed", Detail:
"{str(response.content)}"'
@@ -125,11 +116,8 @@ class EdgeLabel(HugeParamsBase):
@decorator_params
def remove(self):
- url = (
- f"{self._host}/graphs/{self._graph_name}/schema/edgelabels/"
- f'{self._parameter_holder.get_value("name")}'
- )
- response = self.__session.delete(url, auth=self._auth,
headers=self._headers)
+ path = f'schema/edgelabels/{self._parameter_holder.get_value("name")}'
+ response = self._sess.request(path, "DELETE")
self.clean_parameter_holder()
error = RemoveError(
f'RemoveError: "remove EdgeLabel failed", Detail:
"{str(response.content)}"'
@@ -147,12 +135,8 @@ class EdgeLabel(HugeParamsBase):
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
- )
+ path = f'schema/edgelabels/{data["name"]}?action=append'
+ response = self._sess.request(path, "PUT", data=json.dumps(data))
self.clean_parameter_holder()
error = UpdateError(
f'UpdateError: "append EdgeLabel failed", Detail:
"{str(response.content)}"'
@@ -169,11 +153,9 @@ class EdgeLabel(HugeParamsBase):
if self._parameter_holder.get_value("user_data")
else {}
)
- url =
f"{self._host}/graphs/{self._graph_name}/schema/edgelabels/{name}?action=eliminate"
+ path = f"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
- )
+ response = self._sess.request(path, "PUT", data=json.dumps(data))
self.clean_parameter_holder()
error = UpdateError(
f'UpdateError: "eliminate EdgeLabel failed", Detail:
"{str(response.content)}"'
diff --git
a/hugegraph-python-client/src/pyhugegraph/api/schema_manage/index_label.py
b/hugegraph-python-client/src/pyhugegraph/api/schema_manage/index_label.py
index 8eeb437..09ee8aa 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/schema_manage/index_label.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/schema_manage/index_label.py
@@ -25,24 +25,21 @@ from pyhugegraph.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):
+ def onV(self, vertex_label) -> "IndexLabel":
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):
+ def onE(self, edge_label) -> "IndexLabel":
self._parameter_holder.set("base_value", edge_label)
self._parameter_holder.set("base_type", "EDGE_LABEL")
return self
@decorator_params
- def by(self, *args):
+ def by(self, *args) -> "IndexLabel":
if "fields" not in self._parameter_holder.get_keys():
self._parameter_holder.set("fields", set())
s = self._parameter_holder.get_value("fields")
@@ -51,27 +48,24 @@ class IndexLabel(HugeParamsBase):
return self
@decorator_params
- def secondary(self):
+ def secondary(self) -> "IndexLabel":
self._parameter_holder.set("index_type", "SECONDARY")
return self
@decorator_params
- def range(self):
+ def range(self) -> "IndexLabel":
self._parameter_holder.set("index_type", "RANGE")
return self
@decorator_params
- def Search(self):
+ def Search(self) -> "IndexLabel":
self._parameter_holder.set("index_type", "SEARCH")
return self
@decorator_params
- def ifNotExist(self):
- url = (
- f"{self._host}/graphs/{self._graph_name}/schema/indexlabels/"
- f'{self._parameter_holder.get_value("name")}'
- )
- response = self.__session.get(url, auth=self._auth,
headers=self._headers)
+ def ifNotExist(self) -> "IndexLabel":
+ path = f'schema/indexlabels/{self._parameter_holder.get_value("name")}'
+ response = self._sess.request(path)
if response.status_code == 200 and check_if_authorized(response):
self._parameter_holder.set("not_exist", False)
return self
@@ -85,10 +79,8 @@ class IndexLabel(HugeParamsBase):
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
- )
+ path = f"schema/indexlabels"
+ response = self._sess.request(path, "POST", data=json.dumps(data))
self.clean_parameter_holder()
error = CreateError(
f'CreateError: "create IndexLabel failed", Detail
"{str(response.content)}"'
@@ -100,8 +92,8 @@ class IndexLabel(HugeParamsBase):
@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)
+ path = f"schema/indexlabels/{name}"
+ response = self._sess.request(path, "DELETE")
self.clean_parameter_holder()
error = RemoveError(
f'RemoveError: "remove IndexLabel failed", Detail
"{str(response.content)}"'
diff --git
a/hugegraph-python-client/src/pyhugegraph/api/schema_manage/property_key.py
b/hugegraph-python-client/src/pyhugegraph/api/schema_manage/property_key.py
index e9f9e11..e6a1765 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/schema_manage/property_key.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/schema_manage/property_key.py
@@ -25,67 +25,69 @@ from pyhugegraph.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):
+ def asInt(self) -> "PropertyKey":
self._parameter_holder.set("data_type", "INT")
return self
@decorator_params
- def asText(self):
+ def asLong(self) -> "PropertyKey":
+ self._parameter_holder.set("data_type", "LONG")
+ return self
+
+ @decorator_params
+ def asText(self) -> "PropertyKey":
self._parameter_holder.set("data_type", "TEXT")
return self
@decorator_params
- def asDouble(self):
+ def asDouble(self) -> "PropertyKey":
self._parameter_holder.set("data_type", "DOUBLE")
return self
@decorator_params
- def asDate(self):
+ def asDate(self) -> "PropertyKey":
self._parameter_holder.set("data_type", "DATE")
return self
@decorator_params
- def valueSingle(self):
+ def valueSingle(self) -> "PropertyKey":
self._parameter_holder.set("cardinality", "SINGLE")
return self
@decorator_params
- def valueList(self):
+ def valueList(self) -> "PropertyKey":
self._parameter_holder.set("cardinality", "LIST")
return self
@decorator_params
- def valueSet(self):
+ def valueSet(self) -> "PropertyKey":
self._parameter_holder.set("cardinality", "SET")
return self
@decorator_params
- def calcMax(self):
+ def calcMax(self) -> "PropertyKey":
self._parameter_holder.set("aggregate_type", "MAX")
return self
@decorator_params
- def calcMin(self):
+ def calcMin(self) -> "PropertyKey":
self._parameter_holder.set("aggregate_type", "MIN")
return self
@decorator_params
- def calcSum(self):
+ def calcSum(self) -> "PropertyKey":
self._parameter_holder.set("aggregate_type", "SUM")
return self
@decorator_params
- def calcOld(self):
+ def calcOld(self) -> "PropertyKey":
self._parameter_holder.set("aggregate_type", "OLD")
return self
@decorator_params
- def userdata(self, *args):
+ def userdata(self, *args) -> "PropertyKey":
user_data = self._parameter_holder.get_value("user_data")
if not user_data:
self._parameter_holder.set("user_data", {})
@@ -96,12 +98,9 @@ class PropertyKey(HugeParamsBase):
i += 2
return self
- def ifNotExist(self):
- url = (
- f"{self._host}/graphs/{self._graph_name}/schema/propertykeys/"
- f'{self._parameter_holder.get_value("name")}'
- )
- response = self.__session.get(url, auth=self._auth,
headers=self._headers)
+ def ifNotExist(self) -> "PropertyKey":
+ path =
f'schema/propertykeys/{self._parameter_holder.get_value("name")}'
+ response = self._sess.request(path)
if response.status_code == 200 and check_if_authorized(response):
self._parameter_holder.set("not_exist", False)
return self
@@ -114,10 +113,8 @@ class PropertyKey(HugeParamsBase):
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
- )
+ path = "schema/propertykeys"
+ response = self._sess.request(path, "POST",
data=json.dumps(property_keys))
self.clean_parameter_holder()
if check_if_success(
response,
@@ -136,13 +133,8 @@ class PropertyKey(HugeParamsBase):
user_data = {}
data = {"name": property_name, "user_data": user_data}
- url = (
- f"{self._host}/graphs/{self._graph_name}/schema/propertykeys/"
- f"{property_name}/?action=append"
- )
- response = self.__session.put(
- url, data=json.dumps(data), auth=self._auth, headers=self._headers
- )
+ path = f"schema/propertykeys/{property_name}/?action=append"
+ response = self._sess.request(path, "PUT", data=json.dumps(data))
self.clean_parameter_holder()
if check_if_success(
response,
@@ -161,13 +153,8 @@ class PropertyKey(HugeParamsBase):
user_data = {}
data = {"name": property_name, "user_data": user_data}
- url = (
- f"{self._host}/graphs/{self._graph_name}/schema/propertykeys/"
- f"{property_name}/?action=eliminate"
- )
- response = self.__session.put(
- url, data=json.dumps(data), auth=self._auth, headers=self._headers
- )
+ path = f"schema/propertykeys/{property_name}/?action=eliminate"
+ response = self._sess.request(path, "PUT", data=json.dumps(data))
self.clean_parameter_holder()
error = UpdateError(
f'UpdateError: "eliminate PropertyKey failed", Detail:
{str(response.content)}'
@@ -179,8 +166,8 @@ class PropertyKey(HugeParamsBase):
@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, auth=self._auth,
headers=self._headers)
+ path = f'schema/propertykeys/{dic["name"]}'
+ response = self._sess.request(path, "DELETE")
self.clean_parameter_holder()
if check_if_success(
response,
diff --git
a/hugegraph-python-client/src/pyhugegraph/api/schema_manage/vertex_label.py
b/hugegraph-python-client/src/pyhugegraph/api/schema_manage/vertex_label.py
index 0274ad6..a9b49e8 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/schema_manage/vertex_label.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/schema_manage/vertex_label.py
@@ -24,52 +24,49 @@ from pyhugegraph.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):
+ def useAutomaticId(self) -> "VertexLabel":
self._parameter_holder.set("id_strategy", "AUTOMATIC")
return self
@decorator_params
- def useCustomizeStringId(self):
+ def useCustomizeStringId(self) -> "VertexLabel":
self._parameter_holder.set("id_strategy", "CUSTOMIZE_STRING")
return self
@decorator_params
- def useCustomizeNumberId(self):
+ def useCustomizeNumberId(self) -> "VertexLabel":
self._parameter_holder.set("id_strategy", "CUSTOMIZE_NUMBER")
return self
@decorator_params
- def usePrimaryKeyId(self):
+ def usePrimaryKeyId(self) -> "VertexLabel":
self._parameter_holder.set("id_strategy", "PRIMARY_KEY")
return self
@decorator_params
- def properties(self, *args):
+ def properties(self, *args) -> "VertexLabel":
self._parameter_holder.set("properties", list(args))
return self
@decorator_params
- def primaryKeys(self, *args):
+ def primaryKeys(self, *args) -> "VertexLabel":
self._parameter_holder.set("primary_keys", list(args))
return self
@decorator_params
- def nullableKeys(self, *args):
+ def nullableKeys(self, *args) -> "VertexLabel":
self._parameter_holder.set("nullable_keys", list(args))
return self
@decorator_params
- def enableLabelIndex(self, flag):
+ def enableLabelIndex(self, flag) -> "VertexLabel":
self._parameter_holder.set("enable_label_index", flag)
return self
@decorator_params
- def userdata(self, *args):
+ def userdata(self, *args) -> "VertexLabel":
if "user_data" not in self._parameter_holder.get_keys():
self._parameter_holder.set("user_data", {})
user_data = self._parameter_holder.get_value("user_data")
@@ -79,13 +76,9 @@ class VertexLabel(HugeParamsBase):
i += 2
return self
- def ifNotExist(self):
- url = (
- f"{self._host}/graphs/{self._graph_name}/schema/vertexlabels/"
- f'{self._parameter_holder.get_value("name")}'
- )
-
- response = self.__session.get(url, auth=self._auth,
headers=self._headers)
+ def ifNotExist(self) -> "VertexLabel":
+ path =
f'schema/vertexlabels/{self._parameter_holder.get_value("name")}'
+ response = self._sess.request(path)
if response.status_code == 200 and check_if_authorized(response):
self._parameter_holder.set("not_exist", False)
return self
@@ -107,10 +100,8 @@ class VertexLabel(HugeParamsBase):
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
- )
+ path = f"schema/vertexlabels"
+ response = self._sess.request(path, "POST", data=json.dumps(data))
self.clean_parameter_holder()
error = CreateError(
f'CreateError: "create VertexLabel failed", Detail:
"{str(response.content)}"'
@@ -125,20 +116,14 @@ class VertexLabel(HugeParamsBase):
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}"
- f'/schema/vertexlabels/{dic["name"]}?action=append'
- )
-
+ path = f'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
- )
+ response = self._sess.request(path, "PUT", data=json.dumps(data))
self.clean_parameter_holder()
error = UpdateError(
f'UpdateError: "append VertexLabel failed", Detail:
"{str(response.content)}"'
@@ -150,8 +135,8 @@ class VertexLabel(HugeParamsBase):
@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)
+ path = f"schema/vertexlabels/{name}"
+ response = self._sess.request(path, "DELETE")
self.clean_parameter_holder()
error = RemoveError(
f'RemoveError: "remove VertexLabel failed", Detail:
"{str(response.content)}"'
@@ -163,7 +148,7 @@ class VertexLabel(HugeParamsBase):
@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"
+ path = f"schema/vertexlabels/{name}/?action=eliminate"
dic = self._parameter_holder.get_dic()
user_data = dic["user_data"] if "user_data" in dic else {}
@@ -171,9 +156,7 @@ class VertexLabel(HugeParamsBase):
"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
- )
+ response = self._sess.request(path, "PUT", data=json.dumps(data))
error = UpdateError(
f'UpdateError: "eliminate VertexLabel failed", Detail:
"{str(response.content)}"'
)
diff --git a/hugegraph-python-client/src/pyhugegraph/api/task.py
b/hugegraph-python-client/src/pyhugegraph/api/task.py
index fa72540..c31eb8d 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/task.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/task.py
@@ -17,56 +17,37 @@
from pyhugegraph.api.common import HugeParamsBase
from pyhugegraph.utils.exceptions import NotFoundError
-from pyhugegraph.utils.huge_requests import HugeSession
+from pyhugegraph.utils import huge_router as router
from pyhugegraph.utils.util import check_if_success
class TaskManager(HugeParamsBase):
- def __init__(self, graph_instance):
- super().__init__(graph_instance)
- self.__session = HugeSession.new_session()
-
- def close(self):
- if self.__session:
- self.__session.close()
+ @router.http("GET", "tasks")
def list_tasks(self, status=None, limit=None):
- url = f"{self._host}/graphs/{self._graph_name}/tasks"
params = {}
if status is not None:
params["status"] = status
if limit is not None:
params["limit"] = limit
- response = self.__session.get(
- url,
- params=params,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request(params=params)
check_if_success(response, NotFoundError(response.content))
return response.json()
+ @router.http("GET", "tasks/{task_id}")
def get_task(self, task_id):
- url = f"{self._host}/graphs/{self._graph_name}/tasks/{task_id}"
- response = self.__session.get(
- url, auth=self._auth, headers=self._headers, timeout=self._timeout
- )
+ response = self._invoke_request()
check_if_success(response, NotFoundError(response.content))
return response.json()
+ @router.http("DELETE", "tasks/{task_id}")
def delete_task(self, task_id):
- url = f"{self._host}/graphs/{self._graph_name}/tasks/{task_id}"
- response = self.__session.delete(
- url, auth=self._auth, headers=self._headers, timeout=self._timeout
- )
+ response = self._invoke_request()
check_if_success(response, NotFoundError(response.content))
return response.status_code
+ @router.http("PUT", "tasks/{task_id}?action=cancel")
def cancel_task(self, task_id):
- url =
f"{self._host}/graphs/{self._graph_name}/tasks/{task_id}?action=cancel"
- response = self.__session.put(
- url, auth=self._auth, headers=self._headers, timeout=self._timeout
- )
+ response = self._invoke_request()
check_if_success(response, NotFoundError(response.content))
return response.json()
diff --git a/hugegraph-python-client/src/pyhugegraph/api/traverser.py
b/hugegraph-python-client/src/pyhugegraph/api/traverser.py
index b88ea74..165178b 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/traverser.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/traverser.py
@@ -18,125 +18,87 @@ import json
from pyhugegraph.api.common import HugeParamsBase
from pyhugegraph.utils.exceptions import NotFoundError
-from pyhugegraph.utils.huge_requests import HugeSession
+from pyhugegraph.utils import huge_router as router
from pyhugegraph.utils.util import check_if_success
class TraverserManager(HugeParamsBase):
- def __init__(self, graph_instance):
- super().__init__(graph_instance)
- self.url = f"{self._host}/graphs/{self._graph_name}/traversers"
- self.__session = HugeSession.new_session()
-
- def close(self):
- if self.__session:
- self.__session.close()
+ @router.http("GET",
'traversers/kout?source="{source_id}"&max_depth={max_depth}')
def k_out(self, source_id, max_depth):
- url = f'{self.url}/kout?source="{source_id}"&max_depth={max_depth}'
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http(
+ "GET",
'traversers/kneighbor?source="{source_id}"&max_depth={max_depth}'
+ )
def k_neighbor(self, source_id, max_depth):
- url =
f'{self.url}/kneighbor?source="{source_id}"&max_depth={max_depth}'
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http(
+ "GET",
'traversers/sameneighbors?vertex="{vertex_id}"&other="{other_id}"'
+ )
def same_neighbors(self, vertex_id, other_id):
- url =
f'{self.url}/sameneighbors?vertex="{vertex_id}"&other="{other_id}"'
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http(
+ "GET",
'traversers/jaccardsimilarity?vertex="{vertex_id}"&other="{other_id}"'
+ )
def jaccard_similarity(self, vertex_id, other_id):
- url =
f'{self.url}/jaccardsimilarity?vertex="{vertex_id}"&other="{other_id}"'
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http(
+ "GET",
+
'traversers/shortestpath?source="{source_id}"&target="{target_id}"&max_depth={max_depth}',
+ )
def shortest_path(self, source_id, target_id, max_depth):
- url = (
- f"{self.url}/shortestpath?"
- f'source="{source_id}"&target="{target_id}"&max_depth={max_depth}'
- )
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http(
+ "GET",
+
'traversers/allshortestpaths?source="{source_id}"&target="{target_id}"&max_depth={max_depth}',
+ )
def all_shortest_paths(self, source_id, target_id, max_depth):
- url = (
- f"{self.url}/allshortestpaths?"
- f'source="{source_id}"&target="{target_id}"&max_depth={max_depth}'
- )
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http(
+ "GET",
+
'traversers/weightedshortestpath?source="{source_id}"&target="{target_id}"&weight={weight}&max_depth={max_depth}',
+ )
def weighted_shortest_path(self, source_id, target_id, weight, max_depth):
- url = (
- f"{self.url}/weightedshortestpath?"
-
f'source="{source_id}"&target="{target_id}"&weight={weight}&max_depth={max_depth}'
- )
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http(
+ "GET",
+
'traversers/singlesourceshortestpath?source="{source_id}"&max_depth={max_depth}',
+ )
def single_source_shortest_path(self, source_id, max_depth):
- url =
f'{self.url}/singlesourceshortestpath?source="{source_id}"&max_depth={max_depth}'
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("POST", "traversers/multinodeshortestpath")
def multi_node_shortest_path(
self,
vertices,
@@ -148,7 +110,6 @@ class TraverserManager(HugeParamsBase):
):
if properties is None:
properties = {}
- url = f"{self.url}/multinodeshortestpath"
data = {
"vertices": {"ids": vertices},
"step": {"direction": direction, "properties": properties},
@@ -156,34 +117,25 @@ class TraverserManager(HugeParamsBase):
"capacity": capacity,
"with_vertex": with_vertex,
}
- response = self.__session.post(
- url,
- data=json.dumps(data),
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http(
+ "GET",
+
'traversers/paths?source="{source_id}"&target="{target_id}"&max_depth={max_depth}',
+ )
def paths(self, source_id, target_id, max_depth):
- url =
f'{self.url}/paths?source="{source_id}"&target="{target_id}"&max_depth={max_depth}'
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("POST", "traversers/customizedpaths")
def customized_paths(
self, sources, steps, sort_by="INCR", with_vertex=True, capacity=-1,
limit=-1
):
- url = f"{self.url}/customizedpaths"
-
data = {
"sources": sources,
"steps": steps,
@@ -192,19 +144,15 @@ class TraverserManager(HugeParamsBase):
"capacity": capacity,
"limit": limit,
}
- response = self.__session.post(
- url,
- data=json.dumps(data),
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
- def template_paths(self, sources, targets, steps, capacity=10000,
limit=10, with_vertex=True):
- url = f"{self.url}/templatepaths"
+ @router.http("POST", "traversers/templatepaths")
+ def template_paths(
+ self, sources, targets, steps, capacity=10000, limit=10,
with_vertex=True
+ ):
data = {
"sources": sources,
"targets": targets,
@@ -213,36 +161,31 @@ class TraverserManager(HugeParamsBase):
"limit": limit,
"with_vertex": with_vertex,
}
- response = self.__session.post(
- url,
- data=json.dumps(data),
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http(
+ "GET",
+
'traversers/crosspoints?source="{source_id}"&target="{target_id}"&max_depth={max_depth}',
+ )
def crosspoints(self, source_id, target_id, max_depth):
- url = (
- f"{self.url}/crosspoints?"
- f'source="{source_id}"&target="{target_id}"&max_depth={max_depth}'
- )
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("POST", "traversers/customizedcrosspoints")
def customized_crosspoints(
- self, sources, path_patterns, with_path=True, with_vertex=True,
capacity=-1, limit=-1
+ self,
+ sources,
+ path_patterns,
+ with_path=True,
+ with_vertex=True,
+ capacity=-1,
+ limit=-1,
):
- url = f"{self.url}/customizedcrosspoints"
data = {
"sources": sources,
"path_patterns": path_patterns,
@@ -251,41 +194,26 @@ class TraverserManager(HugeParamsBase):
"capacity": capacity,
"limit": limit,
}
- response = self.__session.post(
- url,
- data=json.dumps(data),
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET",
'traversers/rings?source="{source_id}"&max_depth={max_depth}')
def rings(self, source_id, max_depth):
- url = f'{self.url}/rings?source="{source_id}"&max_depth={max_depth}'
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET",
'traversers/rays?source="{source_id}"&max_depth={max_depth}')
def rays(self, source_id, max_depth):
- url = f'{self.url}/rays?source="{source_id}"&max_depth={max_depth}'
- response = self.__session.get(
- url,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("POST", "traversers/fusiformsimilarity")
def fusiform_similarity(
self,
sources,
@@ -303,7 +231,6 @@ class TraverserManager(HugeParamsBase):
with_intermediary=False,
with_vertex=True,
):
- url = f"{self.url}/fusiformsimilarity"
data = {
"sources": sources,
"label": label,
@@ -320,41 +247,23 @@ class TraverserManager(HugeParamsBase):
"with_intermediary": with_intermediary,
"with_vertex": with_vertex,
}
- response = self.__session.post(
- url,
- data=json.dumps(data),
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request(data=json.dumps(data))
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "traversers/vertices")
def vertices(self, ids):
- url = f"{self.url}/vertices"
- params = {"ids": '"' + ids + '"'}
- response = self.__session.get(
- url,
- params=params,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ params = {"ids": f'"{ids}"'}
+ response = self._invoke_request(params=params)
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "traversers/edges")
def edges(self, ids):
- url = f"{self.url}/edges"
params = {"ids": ids}
- response = self.__session.get(
- url,
- params=params,
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request(params=params)
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
diff --git a/hugegraph-python-client/src/pyhugegraph/api/variable.py
b/hugegraph-python-client/src/pyhugegraph/api/variable.py
index 2345bcd..4c060b9 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/variable.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/variable.py
@@ -19,58 +19,34 @@ import json
from pyhugegraph.api.common import HugeParamsBase
from pyhugegraph.utils.exceptions import NotFoundError
-from pyhugegraph.utils.huge_requests import HugeSession
+from pyhugegraph.utils import huge_router as router
from pyhugegraph.utils.util import check_if_success
class VariableManager(HugeParamsBase):
- def __init__(self, graph_instance):
- super().__init__(graph_instance)
- self.__session = HugeSession.new_session()
-
- def close(self):
- if self.__session:
- self.__session.close()
+ @router.http("PUT", "variables/{key}")
def set(self, key, value):
- url = f"{self._host}/graphs/{self._graph_name}/variables/{key}"
- data = {"data": value}
-
- response = self.__session.put(
- url,
- data=json.dumps(data),
- auth=self._auth,
- headers=self._headers,
- timeout=self._timeout,
- )
+ response = self._invoke_request(data=json.dumps({"data": value}))
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "variables/{key}")
def get(self, key):
- url = f"{self._host}/graphs/{self._graph_name}/variables/{key}"
-
- response = self.__session.get(
- url, auth=self._auth, headers=self._headers, timeout=self._timeout
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("GET", "variables")
def all(self):
- url = f"{self._host}/graphs/{self._graph_name}/variables"
-
- response = self.__session.get(
- url, auth=self._auth, headers=self._headers, timeout=self._timeout
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
+ @router.http("DELETE", "variables/{key}")
def remove(self, key):
- url = f"{self._host}/graphs/{self._graph_name}/variables/{key}"
-
- response = self.__session.delete(
- url, auth=self._auth, headers=self._headers, timeout=self._timeout
- )
+ response = self._invoke_request()
check_if_success(response, NotFoundError(response.content))
diff --git a/hugegraph-python-client/src/pyhugegraph/api/version.py
b/hugegraph-python-client/src/pyhugegraph/api/version.py
index 67fc5a5..23b5baf 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/version.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/version.py
@@ -17,24 +17,15 @@
from pyhugegraph.api.common import HugeParamsBase
from pyhugegraph.utils.exceptions import NotFoundError
-from pyhugegraph.utils.huge_requests import HugeSession
+from pyhugegraph.utils import huge_router as router
from pyhugegraph.utils.util import check_if_success
class VersionManager(HugeParamsBase):
- def __init__(self, graph_instance):
- super().__init__(graph_instance)
- self.__session = HugeSession.new_session()
-
- def close(self):
- if self.__session:
- self.__session.close()
+ @router.http("GET", "/versions")
def version(self):
- url = f"{self._host}/versions"
- response = self.__session.get(
- url, auth=self._auth, headers=self._headers, timeout=self._timeout
- )
+ response = self._invoke_request()
if check_if_success(response, NotFoundError(response.content)):
return response.json()
return {}
diff --git a/hugegraph-python-client/src/pyhugegraph/client.py
b/hugegraph-python-client/src/pyhugegraph/client.py
index b833415..fd776ff 100644
--- a/hugegraph-python-client/src/pyhugegraph/client.py
+++ b/hugegraph-python-client/src/pyhugegraph/client.py
@@ -14,8 +14,10 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
+
+from typing import Optional
+
from pyhugegraph.api.auth import AuthManager
-from pyhugegraph.api.common import HugeParamsBase
from pyhugegraph.api.graph import GraphManager
from pyhugegraph.api.graphs import GraphsManager
from pyhugegraph.api.gremlin import GremlinManager
@@ -25,60 +27,74 @@ from pyhugegraph.api.task import TaskManager
from pyhugegraph.api.traverser import TraverserManager
from pyhugegraph.api.variable import VariableManager
from pyhugegraph.api.version import VersionManager
-from pyhugegraph.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
- self._variable = None
- self._auth = None
- self._task = None
- self._metrics = None
- self._traverser = None
- self._version = None
-
- def schema(self):
- self._schema = self._schema or SchemaManager(self._graph_instance)
- return self._schema
-
- def gremlin(self):
- self._gremlin = self._gremlin or GremlinManager(self._graph_instance)
- return self._gremlin
-
- def graph(self):
- self._graph = self._graph or GraphManager(self._graph_instance)
- return self._graph
-
- def graphs(self):
- self._graphs = self._graphs or GraphsManager(self._graph_instance)
- return self._graphs
-
- def variable(self):
- self._variable = self._variable or
VariableManager(self._graph_instance)
- return self._variable
-
- def auth(self):
- self._auth = self._auth or AuthManager(self._graph_instance)
- return self._auth
-
- def task(self):
- self._task = self._task or TaskManager(self._graph_instance)
- return self._task
-
- def metrics(self):
- self._metrics = self._metrics or MetricsManager(self._graph_instance)
- return self._metrics
-
- def traverser(self):
- self._traverser = self._traverser or
TraverserManager(self._graph_instance)
- return self._traverser
-
- def version(self):
- self._version = self._version or VersionManager(self._graph_instance)
- return self._version
+from pyhugegraph.utils.huge_config import HGraphConfig
+from pyhugegraph.utils.huge_requests import HGraphSession
+
+
+def manager_builder(fn):
+ attr_name = "_lazy_" + fn.__name__
+
+ def wrapper(self: "PyHugeClient"):
+ if not hasattr(self, attr_name):
+ session = HGraphSession(self._cfg)
+ setattr(self, attr_name, fn(self)(session))
+ return getattr(self, attr_name)
+
+ return wrapper
+
+
+class PyHugeClient:
+ def __init__(
+ self,
+ ip: str,
+ port: str,
+ graph: str,
+ user: str,
+ pwd: str,
+ timeout: int = 10,
+ gs: Optional[str] = None,
+ ):
+ self._cfg = HGraphConfig(ip, port, user, pwd, graph, gs, timeout)
+
+ @manager_builder
+ def schema(self) -> "SchemaManager":
+ return SchemaManager
+
+ @manager_builder
+ def gremlin(self) -> "GremlinManager":
+ return GremlinManager
+
+ @manager_builder
+ def graph(self) -> "GraphManager":
+ return GraphManager
+
+ @manager_builder
+ def graphs(self) -> "GraphsManager":
+ return GraphsManager
+
+ @manager_builder
+ def variable(self) -> "VariableManager":
+ return VariableManager
+
+ @manager_builder
+ def auth(self) -> "AuthManager":
+ return AuthManager
+
+ @manager_builder
+ def task(self) -> "TaskManager":
+ return TaskManager
+
+ @manager_builder
+ def metrics(self) -> "MetricsManager":
+ return MetricsManager
+
+ @manager_builder
+ def traverser(self) -> "TraverserManager":
+ return TraverserManager
+
+ @manager_builder
+ def version(self) -> "VersionManager":
+ return VersionManager
+
+ def __repr__(self) -> str:
+ return f"{self._cfg}"
diff --git
a/hugegraph-python-client/src/pyhugegraph/example/hugegraph_example.py
b/hugegraph-python-client/src/pyhugegraph/example/hugegraph_example.py
index 27d0246..d58190e 100644
--- a/hugegraph-python-client/src/pyhugegraph/example/hugegraph_example.py
+++ b/hugegraph-python-client/src/pyhugegraph/example/hugegraph_example.py
@@ -18,19 +18,23 @@
from pyhugegraph.client import PyHugeClient
if __name__ == "__main__":
- client = PyHugeClient("127.0.0.1", "8080", user="admin", pwd="admin",
graph="hugegraph")
+ client = PyHugeClient(
+ "127.0.0.1", "8080", user="admin", pwd="admin", graph="hugegraph"
+ )
"""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("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()
+ schema.edgeLabel("ActedIn").sourceLabel("Person").targetLabel(
+ "Movie"
+ ).ifNotExist().create()
print(schema.getVertexLabels())
print(schema.getEdgeLabels())
@@ -43,7 +47,9 @@ if __name__ == "__main__":
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"})
+ m3 = g.addVertex(
+ "Movie", {"name": "The Godfather Coda The Death of Michael Corleone"}
+ )
# add Edge
g.addEdge("ActedIn", p1.id, m1.id, {})
diff --git a/hugegraph-python-client/src/pyhugegraph/example/hugegraph_test.py
b/hugegraph-python-client/src/pyhugegraph/example/hugegraph_test.py
index 8b47f51..739862d 100644
--- a/hugegraph-python-client/src/pyhugegraph/example/hugegraph_test.py
+++ b/hugegraph-python-client/src/pyhugegraph/example/hugegraph_test.py
@@ -41,7 +41,9 @@ class HugeGraph:
self.address = address
self.port = port
self.graph = graph
- self.client = PyHugeClient(address, port, user=username, pwd=password,
graph=graph)
+ self.client = PyHugeClient(
+ address, port, user=username, pwd=password, graph=graph
+ )
self.schema = ""
def exec(self, query) -> str:
diff --git
a/hugegraph-python-client/src/pyhugegraph/structure/graph_instance.py
b/hugegraph-python-client/src/pyhugegraph/structure/graph_instance.py
deleted file mode 100644
index 08b390e..0000000
--- a/hugegraph-python-client/src/pyhugegraph/structure/graph_instance.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# 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.__graphspace = graphspace
- 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},"
- f" user_name:{self.user_name}, passwd:{self.passwd},
timeout:{self.timeout}"
- )
- return res
diff --git
a/hugegraph-python-client/src/pyhugegraph/structure/property_key_data.py
b/hugegraph-python-client/src/pyhugegraph/structure/property_key_data.py
index 9b7b50c..6fb7c36 100644
--- a/hugegraph-python-client/src/pyhugegraph/structure/property_key_data.py
+++ b/hugegraph-python-client/src/pyhugegraph/structure/property_key_data.py
@@ -15,6 +15,23 @@
# specific language governing permissions and limitations
# under the License.
+# from dataclasses import dataclass, field
+
+
+# @dataclass
+# class PropertyKeyData:
+# id: int
+# name: str
+# cardinality: str
+# data_type: str
+# properties: list = field(default_factory=list)
+# user_data: dict = field(default_factory=dict)
+
+# @classmethod
+# def from_dict(cls, data: dict):
+# filtered_data = {k: v for k, v in data.items() if k in
cls.__annotations__}
+# return cls(**filtered_data)
+
class PropertyKeyData:
def __init__(self, dic):
@@ -45,7 +62,5 @@ class PropertyKeyData:
return self.__user_data
def __repr__(self):
- res = (
- f"name: {self.__name}, cardinality: {self.__cardinality},
data_type: {self.__data_type}"
- )
+ res = f"name: {self.__name}, cardinality: {self.__cardinality},
data_type: {self.__data_type}"
return res
diff --git a/hugegraph-python-client/src/pyhugegraph/utils/huge_config.py
b/hugegraph-python-client/src/pyhugegraph/utils/huge_config.py
new file mode 100644
index 0000000..f7e00d9
--- /dev/null
+++ b/hugegraph-python-client/src/pyhugegraph/utils/huge_config.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.
+
+import re
+import requests
+import traceback
+
+from dataclasses import dataclass, field
+from typing import Optional, List
+
+
+@dataclass
+class HGraphConfig:
+ ip: str
+ port: str
+ username: str
+ password: str
+ graph_name: str
+ graphspace: Optional[str] = None
+ timeout: int = 10
+ gs_supported: bool = field(default=False, init=False)
+ version: List[int] = field(default_factory=list)
+
+ def __post_init__(self):
+
+ if self.graphspace is not None:
+ self.gs_supported = True
+
+ else:
+ try:
+ response = requests.get(
+ f"http://{self.ip}:{self.port}/versions", timeout=1
+ )
+ core = response.json()["versions"]["core"]
+ print(f"Retrieved API version information from the server:
{core}.")
+
+ match = re.search("(\d+)\.(\d+)(?:\.(\d+))?(?:\.\d+)?", core)
+ major, minor, patch = map(int, match.groups())
+ self.version.extend([major, minor, patch])
+
+ if major >= 3:
+ self.graphspace = "DEFAULT"
+ self.gs_supported = True
+ print(
+ f"graph space is not set, default value 'DEFAULT' will
be used."
+ )
+
+ except Exception as e:
+ traceback.print_exception(e)
+ self.gs_supported = False
+ print(
+ "Failed to retrieve API version information from the
server, reverting to default v1."
+ )
diff --git a/hugegraph-python-client/src/pyhugegraph/utils/huge_decorator.py
b/hugegraph-python-client/src/pyhugegraph/utils/huge_decorator.py
index b7151f3..ecc94bf 100644
--- a/hugegraph-python-client/src/pyhugegraph/utils/huge_decorator.py
+++ b/hugegraph-python-client/src/pyhugegraph/utils/huge_decorator.py
@@ -15,6 +15,7 @@
# specific language governing permissions and limitations
# under the License.
+
from decorator import decorator
from pyhugegraph.utils.exceptions import NotAuthorizedError
diff --git a/hugegraph-python-client/src/pyhugegraph/utils/huge_requests.py
b/hugegraph-python-client/src/pyhugegraph/utils/huge_requests.py
index 57ac233..83ecece 100644
--- a/hugegraph-python-client/src/pyhugegraph/utils/huge_requests.py
+++ b/hugegraph-python-client/src/pyhugegraph/utils/huge_requests.py
@@ -18,15 +18,101 @@
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
+from urllib.parse import urljoin
+from typing import Any, Optional
+from pyhugegraph.utils.constants import Constants
+from pyhugegraph.utils.huge_config import HGraphConfig
-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
+
+class HGraphSession:
+ def __init__(
+ self,
+ cfg: HGraphConfig,
+ retries: int = 5,
+ backoff_factor: int = 1,
+ status_forcelist=(500, 502, 504),
+ session: Optional[requests.Session] = None,
+ ):
+ """
+ Initialize the HGraphSession object.
+ :param retries: The maximum number of retries.
+ :param backoff_factor: The backoff factor, used to calculate the
interval between retries.
+ :param status_forcelist: A list of status codes that trigger a retry.
+ :param session: An optional requests.Session instance, for testing or
advanced use cases.
+ """
+ self._cfg = cfg
+ self._retries = retries
+ self._backoff_factor = backoff_factor
+ self._status_forcelist = status_forcelist
+ self._auth = (cfg.username, cfg.password)
+ self._headers = {"Content-Type": Constants.HEADER_CONTENT_TYPE}
+ self._timeout = cfg.timeout
+ self._session = session if session else requests.Session()
+ self.__configure_session()
+
+ def __configure_session(self):
+ """
+ Configure the retry strategy and connection adapter for the session.
+ """
+ retry_strategy = Retry(
+ total=self._retries,
+ read=self._retries,
+ connect=self._retries,
+ backoff_factor=self._backoff_factor,
+ status_forcelist=self._status_forcelist,
+ )
+ adapter = HTTPAdapter(max_retries=retry_strategy)
+ self._session.mount("http://", adapter)
+ self._session.mount("https://", adapter)
+ self._session.keep_alive = False
+ # logger.debug(
+ # "Session configured with retries=%s and backoff_factor=%s",
+ # self.retries,
+ # self.backoff_factor,
+ # )
+
+ def resolve(self, path: str):
+ """
+ Constructs the full URL for the given pathinfo based on the session
context and API version.
+
+ :param path: The pathinfo to be appended to the base URL.
+ :return: The fully resolved URL as a string.
+
+ When path is "/some/things":
+ - Since path starts with "/", it is considered an absolute path, and
urljoin will replace the path part of the base URL.
+ - Assuming the base URL is
"http://127.0.0.1:8000/graphspaces/default/graphs/test_graph/"
+ - The result will be "http://127.0.0.1:8000/some/things"
+
+ When path is "some/things":
+ - Since path is a relative path, urljoin will append it to the path
part of the base URL.
+ - Assuming the base URL is
"http://127.0.0.1:8000/graphspaces/default/graphs/test_graph/"
+ - The result will be
"http://127.0.0.1:8000/graphspaces/default/graphs/test_graph/some/things"
+ """
+
+ url = f"http://{self._cfg.ip}:{self._cfg.port}/"
+ if self._cfg.gs_supported:
+ url = urljoin(
+ url,
+
f"graphspaces/{self._cfg.graphspace}/graphs/{self._cfg.graph_name}/",
+ )
+ else:
+ url = urljoin(url, f"graphs/{self._cfg.graph_name}/")
+ return urljoin(url, path).strip("/")
+
+ def close(self):
+ self._session.close()
+
+ def request(self, path: str, method: str = "GET", **kwargs: Any):
+ try:
+ # print(method, self.resolve(path))
+ response = getattr(self._session, method.lower())(
+ self.resolve(path),
+ auth=self._auth,
+ headers=self._headers,
+ timeout=self._timeout,
+ **kwargs,
+ )
+ return response
+ except requests.RequestException as e:
+ raise
diff --git a/hugegraph-python-client/src/pyhugegraph/utils/huge_router.py
b/hugegraph-python-client/src/pyhugegraph/utils/huge_router.py
new file mode 100644
index 0000000..08f9311
--- /dev/null
+++ b/hugegraph-python-client/src/pyhugegraph/utils/huge_router.py
@@ -0,0 +1,130 @@
+# 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 re
+import json
+import inspect
+import functools
+import threading
+
+from abc import ABC
+from typing import Any, Callable, Dict, TYPE_CHECKING
+
+if TYPE_CHECKING:
+ from pyhugegraph.api.common import HGraphContext
+
+
+class SingletonBase(type):
+ _instances = {}
+ _lock = threading.Lock()
+
+ def __call__(cls, *args, **kwargs):
+ """
+ Ensure that only one instance of the class is created.
+ If an instance already exists, return it; otherwise, create a new one.
+ This method is thread-safe.
+ """
+ with cls._lock:
+ if cls not in cls._instances:
+ cls._instances[cls] = super().__call__(*args, **kwargs)
+ return cls._instances[cls]
+
+
+class HGraphRouterManager(metaclass=SingletonBase):
+ def __init__(self):
+ self._routers = {}
+
+ def register(self, key, path):
+ self._routers.update({key: path})
+
+ def get_routers(self):
+ return self._routers
+
+ def __repr__(self) -> str:
+ return json.dumps(self._routers, indent=4)
+
+
+def http(method: str, path: str) -> Callable:
+ """
+ A decorator to format the pathinfo and inject a request function into the
decorated method.
+
+ Args:
+ method (str): The HTTP method to be used (e.g., 'GET', 'POST').
+ path (str): The pathinfo template to be formatted with function
arguments.
+
+ Returns:
+ Callable: The decorator function.
+ """
+
+ def decorator(func: Callable) -> Callable:
+ """Decorator function that modifies the original function."""
+ HGraphRouterManager().register(func.__qualname__, (method, path))
+
+ @functools.wraps(func)
+ def wrapper(self: "HGraphContext", *args: Any, **kwargs: Any) -> Any:
+ """
+ Wrapper function to format the pathinfo and create a partial
request function.
+
+ Args:
+ self (HGraphContext): The instance of the class.
+ *args (Any): Positional arguments to the decorated function.
+ **kwargs (Any): Keyword arguments to the decorated function.
+
+ Returns:
+ Any: The result of the decorated function.
+ """
+ # If the pathinfo contains placeholders, format it with the actual
arguments
+ if re.search(r"{\w+}", path):
+ sig = inspect.signature(func)
+ bound_args = sig.bind(self, *args, **kwargs)
+ bound_args.apply_defaults()
+ all_kwargs = dict(bound_args.arguments)
+ # Remove 'self' from the arguments used to format the pathinfo
+ all_kwargs.pop("self")
+ formatted_path = path.format(**all_kwargs)
+ else:
+ formatted_path = path
+
+ # todo: If possible, reduce unnecessary multiple creations.
+ cache_key = (func.__qualname__, method, formatted_path)
+ # Use functools.partial to create a partial function for making
requests
+ make_request = functools.partial(self._sess.request,
formatted_path, method)
+ # Store the partial function on the instance
+ setattr(self, f"_{func.__name__}_request", make_request)
+
+ return func(self, *args, **kwargs)
+
+ return wrapper
+
+ return decorator
+
+
+class HGraphRouter(ABC):
+
+ def _invoke_request(self, **kwargs: Any):
+ """
+ Make an HTTP request using the stored partial request function.
+
+ Args:
+ **kwargs (Any): Keyword arguments to be passed to the request
function.
+
+ Returns:
+ Any: The response from the HTTP request.
+ """
+ frame = inspect.currentframe().f_back
+ fname = frame.f_code.co_name
+ return getattr(self, f"_{fname}_request")(**kwargs)
diff --git a/hugegraph-python-client/src/pyhugegraph/utils/log.py
b/hugegraph-python-client/src/pyhugegraph/utils/log.py
new file mode 100755
index 0000000..18dac65
--- /dev/null
+++ b/hugegraph-python-client/src/pyhugegraph/utils/log.py
@@ -0,0 +1,75 @@
+# 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 logging
+from logging.handlers import TimedRotatingFileHandler
+import os
+
+# Set log format
+LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
+DATE_FORMAT = "%Y-%m-%d %H:%M:%S %p"
+
+
+# Function to configure logging path, default is "logs/output.log"
+# You could import it in "__init__.py" & use it in the whole package
+def init_log(log_file="logs/output.log"):
+ # Ensure the log directory exists
+ log_dir = os.path.dirname(log_file)
+ os.makedirs(log_dir, exist_ok=True)
+
+ # Create a logger
+ log = logging.getLogger(__name__)
+ log.setLevel(logging.DEBUG)
+
+ # Create a handler for writing to log file
+ file_handler = TimedRotatingFileHandler(log_file, when='midnight',
interval=1, backupCount=3, encoding='utf-8')
+ file_handler.setLevel(logging.DEBUG)
+ file_handler.setFormatter(logging.Formatter(LOG_FORMAT,
datefmt=DATE_FORMAT))
+ log.addHandler(file_handler)
+
+ # ANSI escape sequences for colors
+ class CustomConsoleHandler(logging.StreamHandler):
+ COLORS = {
+ "DEBUG": "\033[0;37m", # White
+ "INFO": "\033[0;32m", # Green
+ "WARNING": "\033[0;33m", # Yellow
+ "ERROR": "\033[0;31m", # Red
+ "CRITICAL": "\033[0;41m" # Red background
+ }
+
+ def emit(self, record):
+ try:
+ msg = self.format(record)
+ level = record.levelname
+ color_prefix = self.COLORS.get(level, "\033[0;37m") # Default
to white
+ color_suffix = "\033[0m" # Reset to default
+ stream = self.stream
+ stream.write(color_prefix + msg + color_suffix +
self.terminator)
+ self.flush()
+ except Exception as e:
+ self.handleError(record)
+ log.error(f"Log Print Exception: {e}")
+
+ # Also output logs to the console
+ custom_handler = CustomConsoleHandler()
+ custom_handler.setLevel(logging.DEBUG)
+ custom_handler.setFormatter(logging.Formatter(LOG_FORMAT,
datefmt=DATE_FORMAT))
+ log.addHandler(custom_handler)
+
+ return log
+
+
+# Default logger configuration
+log = init_log()
diff --git a/hugegraph-python-client/src/pyhugegraph/utils/util.py
b/hugegraph-python-client/src/pyhugegraph/utils/util.py
index 6372587..5ca36b3 100644
--- a/hugegraph-python-client/src/pyhugegraph/utils/util.py
+++ b/hugegraph-python-client/src/pyhugegraph/utils/util.py
@@ -43,7 +43,9 @@ def check_if_authorized(response):
def check_if_success(response, error=None):
- if (not str(response.status_code).startswith("20")) and
check_if_authorized(response):
+ if (not str(response.status_code).startswith("20")) and
check_if_authorized(
+ response
+ ):
if error is None:
error = NotFoundError(response.content)
@@ -51,8 +53,10 @@ def check_if_success(response, error=None):
req_body = req.body if req.body else "Empty body"
response_body = response.text if response.text else "Empty body"
# Log the detailed information
- print(f"\033[93mError-Client:\n"
- f"Request URL: {req.url}, Request Body: {req_body}\nResponse
Body: "
- f"{response_body}\033[0m")
+ print(
+ f"\033[93mError-Client:\n"
+ f"Request URL: {req.url}, Request Body: {req_body}\nResponse Body:
"
+ f"{response_body}\033[0m"
+ )
raise error
return True
diff --git a/hugegraph-python-client/src/tests/api/test_auth.py
b/hugegraph-python-client/src/tests/api/test_auth.py
index 10e6bad..d2d30cf 100644
--- a/hugegraph-python-client/src/tests/api/test_auth.py
+++ b/hugegraph-python-client/src/tests/api/test_auth.py
@@ -98,7 +98,9 @@ class TestAuthManager(unittest.TestCase):
self.assertEqual(group["group_name"], "test_group")
# Modify the group
- group = self.auth.modify_group(group["id"],
group_description="test_description")
+ group = self.auth.modify_group(
+ group["id"], group_description="test_description"
+ )
self.assertEqual(group["group_description"], "test_description")
# Delete the group
@@ -133,7 +135,9 @@ class TestAuthManager(unittest.TestCase):
[{"type": "VERTEX", "label": "person", "properties": {"city":
"Shanghai"}}],
)
# Verify the target was modified
- self.assertEqual(target["target_resources"][0]["properties"]["city"],
"Shanghai")
+ self.assertEqual(
+ target["target_resources"][0]["properties"]["city"], "Shanghai"
+ )
# Delete the target
self.auth.delete_target(target["id"])