This is an automated email from the ASF dual-hosted git repository.

liuxiaocs pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-hugegraph-ai.git


The following commit(s) were added to refs/heads/main by this push:
     new f767a5e  feat: add auth&metric&traverser&task api and ut (#28)
f767a5e is described below

commit f767a5e88191bdb96d68d177a4e928583a0c1027
Author: Simon Cheung <[email protected]>
AuthorDate: Sun Feb 25 11:43:10 2024 +0800

    feat: add auth&metric&traverser&task api and ut (#28)
    
    * add config util & add wenxinyiyan
    
    * add spo triple info extraction
    
    * add code_format_and_analysis.sh
    
    * fix pyhugegraph code style & add ut
    
    * auth/metric/traverser/task
    
    * Update hugegraph-python-client.yml
    
    * fix codestyle
---
 .github/workflows/hugegraph-python-client.yml      |   2 +-
 .../src/pyhugegraph/api/auth.py                    | 363 +++++++++++++++++++++
 .../src/pyhugegraph/api/graph.py                   | 115 ++++---
 .../src/pyhugegraph/api/graphs.py                  |  20 +-
 .../src/pyhugegraph/api/gremlin.py                 |  14 +-
 .../src/pyhugegraph/api/metric.py                  | 139 ++++++++
 .../src/pyhugegraph/api/schema.py                  |  64 ++--
 .../pyhugegraph/api/schema_manage/edge_label.py    |  26 +-
 .../pyhugegraph/api/schema_manage/index_label.py   |  16 +-
 .../pyhugegraph/api/schema_manage/property_key.py  |  44 ++-
 .../pyhugegraph/api/schema_manage/vertex_label.py  |  28 +-
 .../src/pyhugegraph/api/{variable.py => task.py}   |  66 ++--
 .../src/pyhugegraph/api/traverser.py               | 360 ++++++++++++++++++++
 .../src/pyhugegraph/api/variable.py                |  18 +-
 hugegraph-python-client/src/pyhugegraph/client.py  |  45 ++-
 .../src/pyhugegraph/structure/edge_label_data.py   |   8 +
 .../src/pyhugegraph/structure/vertex_label_data.py |   8 +
 .../src/pyhugegraph/utils/huge_decorator.py        |   2 +-
 .../src/pyhugegraph/utils/util.py                  |   4 +-
 hugegraph-python-client/src/tests/api/test_auth.py | 209 ++++++++++++
 .../src/tests/api/test_graph.py                    | 161 +++++++++
 .../src/tests/api/test_graphs.py                   |  60 ++++
 .../src/tests/api/test_gremlin.py                  |  21 +-
 .../src/tests/api/test_metric.py                   |  73 +++++
 .../src/tests/api/test_schema.py                   |  81 +++++
 hugegraph-python-client/src/tests/api/test_task.py |  64 ++++
 .../src/tests/api/test_traverser.py                | 259 +++++++++++++++
 .../src/tests/api/test_variable.py                 |  24 +-
 hugegraph-python-client/src/tests/client_utils.py  |  19 ++
 style/code_format_and_analysis.sh                  |   2 +-
 style/pylint.conf                                  |   8 +-
 31 files changed, 2093 insertions(+), 230 deletions(-)

diff --git a/.github/workflows/hugegraph-python-client.yml 
b/.github/workflows/hugegraph-python-client.yml
index 450ebf5..61fabb6 100644
--- a/.github/workflows/hugegraph-python-client.yml
+++ b/.github/workflows/hugegraph-python-client.yml
@@ -26,7 +26,7 @@ jobs:
         pip install -r ./hugegraph-python-client/requirements.txt
     - name: Prepare HugeGraph Server Environment
       run: |
-        docker run -d --name=graph -p 8080:8080 hugegraph/hugegraph
+        docker run -d --name=graph -p 8080:8080 -e PASSWORD=admin 
hugegraph/hugegraph:1.2.0
         sleep 20
     - name: Test example
       run: |
diff --git a/hugegraph-python-client/src/pyhugegraph/api/auth.py 
b/hugegraph-python-client/src/pyhugegraph/api/auth.py
new file mode 100644
index 0000000..0ce1103
--- /dev/null
+++ b/hugegraph-python-client/src/pyhugegraph/api/auth.py
@@ -0,0 +1,363 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+import json
+
+from pyhugegraph.api.common import HugeParamsBase
+from pyhugegraph.utils.exceptions import NotFoundError
+from pyhugegraph.utils.huge_requests import HugeSession
+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()
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return []
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            if response.status_code != 204:
+                return response.json()
+        return {}
+
+    def modify_user(
+        self,
+        user_id,
+        user_name=None,
+        user_password=None,
+        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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return []
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            if response.status_code != 204:
+                return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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
+        )
+        check_if_success(response, NotFoundError(response.content))
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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
+        )
+        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}"
+        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,
+        )
+        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
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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
+        )
+        check_if_success(response, NotFoundError(response.content))
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
diff --git a/hugegraph-python-client/src/pyhugegraph/api/graph.py 
b/hugegraph-python-client/src/pyhugegraph/api/graph.py
index 1b3fefa..959e6b0 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/graph.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/graph.py
@@ -37,15 +37,11 @@ from pyhugegraph.utils.util import (
 class GraphManager(HugeParamsBase):
     def __init__(self, graph_instance):
         super().__init__(graph_instance)
-        self.session = self.set_session(HugeSession.new_session())
-
-    def set_session(self, session):
-        self.session = session
-        return session
+        self.__session = HugeSession.new_session()
 
     def close(self):
-        if self.session:
-            self.session.close()
+        if self.__session:
+            self.__session.close()
 
     def addVertex(self, label, properties, id=None):
         data = {}
@@ -54,16 +50,19 @@ class GraphManager(HugeParamsBase):
         data["label"] = label
         data["properties"] = properties
         url = f"{self._host}/graphs/{self._graph_name}/graph/vertices"
-        response = self.session.post(
+        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"create vertex failed: 
{response.content}")):
+        if check_if_success(
+            response, CreateError(f"create vertex failed: 
{str(response.content)}")
+        ):
             res = VertexData(json.loads(response.content))
             return res
+        return None
 
     def addVertices(self, input_data):
         url = f"{self._host}/graphs/{self._graph_name}/graph/vertices/batch"
@@ -71,33 +70,39 @@ class GraphManager(HugeParamsBase):
         data = []
         for item in input_data:
             data.append({"label": item[0], "properties": item[1]})
-        response = self.session.post(
+        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"create vertexes failed: 
{response.content}")):
+        if check_if_success(
+            response, CreateError(f"create vertexes failed: 
{str(response.content)}")
+        ):
             res = []
             for item in json.loads(response.content):
                 res.append(VertexData({"id": item}))
             return res
+        return None
 
     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(
+        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 vertex failed: 
{response.content}")):
+        if check_if_success(
+            response, UpdateError(f"append vertex failed: 
{str(response.content)}")
+        ):
             res = VertexData(json.loads(response.content))
             return res
+        return None
 
     def eliminateVertex(self, vertex_id, properties):
         url = (
@@ -105,28 +110,32 @@ class GraphManager(HugeParamsBase):
         )
 
         data = {"properties": properties}
-        response = self.session.put(
+        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"eliminate vertex failed: 
{response.content}")):
+        if check_if_success(
+            response, UpdateError(f"eliminate vertex failed: 
{str(response.content)}")
+        ):
             res = VertexData(json.loads(response.content))
             return res
+        return None
 
     def getVertexById(self, vertex_id):
         url = 
f'{self._host}/graphs/{self._graph_name}/graph/vertices/"{vertex_id}"'
 
-        response = self.session.get(
+        response = self.__session.get(
             url, auth=self._auth, headers=self._headers, timeout=self._timeout
         )
-        if check_if_success(response, NotFoundError(f"Vertex not found: 
{response.content}")):
+        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, properties=None):
+    def getVertexByPage(self, label, limit, page=None, properties=None):
         url = f"{self._host}/graphs/{self._graph_name}/graph/vertices?"
 
         para = ""
@@ -139,17 +148,18 @@ class GraphManager(HugeParamsBase):
             para += "&page"
         para = para + "&limit=" + str(limit)
         url = url + para[1:]
-        response = self.session.get(
+        response = self.__session.get(
             url, auth=self._auth, headers=self._headers, timeout=self._timeout
         )
-        if check_if_success(response, NotFoundError(f"Vertex not found: 
{response.content}")):
+        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))
             next_page = json.loads(response.content)["page"]
             return res, next_page
+        return None
 
-    def getVertexByCondition(self, label="", limit=0, page="", 
properties=None):
+    def getVertexByCondition(self, label="", limit=0, page=None, 
properties=None):
         url = f"{self._host}/graphs/{self._graph_name}/graph/vertices?"
 
         para = ""
@@ -164,22 +174,26 @@ class GraphManager(HugeParamsBase):
         else:
             para += "&page"
         url = url + para[1:]
-        response = self.session.get(
+        response = self.__session.get(
             url, auth=self._auth, headers=self._headers, timeout=self._timeout
         )
-        if check_if_success(response, NotFoundError(f"Vertex not found: 
{response.content}")):
+        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
 
     def removeVertexById(self, vertex_id):
         url = 
f'{self._host}/graphs/{self._graph_name}/graph/vertices/"{vertex_id}"'
-        response = self.session.delete(
+        response = self.__session.delete(
             url, auth=self._auth, headers=self._headers, timeout=self._timeout
         )
-        if check_if_success(response, RemoveError(f"remove vertex failed: 
{response.content}")):
+        if check_if_success(
+            response, RemoveError(f"remove vertex failed: 
{str(response.content)}")
+        ):
             return response.content
+        return None
 
     def addEdge(self, edge_label, out_id, in_id, properties):
         url = f"{self._host}/graphs/{self._graph_name}/graph/edges"
@@ -190,16 +204,17 @@ class GraphManager(HugeParamsBase):
             "inV": in_id,
             "properties": properties,
         }
-        response = self.session.post(
+        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: 
{response.content}")):
+        if check_if_success(response, CreateError(f"created edge failed: 
{str(response.content)}")):
             res = EdgeData(json.loads(response.content))
             return res
+        return None
 
     def addEdges(self, input_data):
         url = f"{self._host}/graphs/{self._graph_name}/graph/edges/batch"
@@ -216,58 +231,66 @@ class GraphManager(HugeParamsBase):
                     "properties": item[5],
                 }
             )
-        response = self.session.post(
+        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 edges failed:  
{response.content}")):
+        if check_if_success(
+            response, CreateError(f"created edges failed:  
{str(response.content)}")
+        ):
             res = []
             for item in json.loads(response.content):
                 res.append(EdgeData({"id": item}))
             return res
+        return None
 
     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(
+        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: 
{response.content}")):
+        if check_if_success(response, UpdateError(f"append edge failed: 
{str(response.content)}")):
             res = EdgeData(json.loads(response.content))
             return res
+        return None
 
     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(
+        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"eliminate edge failed: 
{response.content}")):
+        if check_if_success(
+            response, UpdateError(f"eliminate edge failed: 
{str(response.content)}")
+        ):
             res = EdgeData(json.loads(response.content))
             return res
+        return None
 
     def getEdgeById(self, edge_id):
         url = f"{self._host}/graphs/{self._graph_name}/graph/edges/{edge_id}"
 
-        response = self.session.get(
+        response = self.__session.get(
             url, auth=self._auth, headers=self._headers, timeout=self._timeout
         )
-        if check_if_success(response, NotFoundError(f"not found edge: 
{response.content}")):
+        if check_if_success(response, NotFoundError(f"not found edge: 
{str(response.content)}")):
             res = EdgeData(json.loads(response.content))
             return res
+        return None
 
     def getEdgeByPage(
         self,
@@ -297,23 +320,25 @@ class GraphManager(HugeParamsBase):
         if limit > 0:
             para = para + "&limit=" + str(limit)
         url = url + para[1:]
-        response = self.session.get(
+        response = self.__session.get(
             url, auth=self._auth, headers=self._headers, timeout=self._timeout
         )
-        if check_if_success(response, NotFoundError(f"not found edges: 
{response.content}")):
+        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
 
     def removeEdgeById(self, edge_id):
         url = f"{self._host}/graphs/{self._graph_name}/graph/edges/{edge_id}"
 
-        response = self.session.delete(
+        response = self.__session.delete(
             url, auth=self._auth, headers=self._headers, timeout=self._timeout
         )
-        if check_if_success(response, RemoveError(f"remove edge failed: 
{response.content}")):
+        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:
@@ -322,7 +347,7 @@ class GraphManager(HugeParamsBase):
         for vertex_id in vertex_ids:
             url += f'ids="{vertex_id}"&'
         url = url.rstrip("&")
-        response = self.session.get(
+        response = self.__session.get(
             url, auth=self._auth, headers=self._headers, timeout=self._timeout
         )
         if response.status_code == 200 and check_if_authorized(response):
@@ -330,8 +355,8 @@ class GraphManager(HugeParamsBase):
             for item in json.loads(response.content)["vertices"]:
                 res.append(VertexData(item))
             return res
-        else:
-            create_exception(response.content)
+        create_exception(response.content)
+        return None
 
     def getEdgesById(self, edge_ids):
         if not edge_ids:
@@ -340,7 +365,7 @@ class GraphManager(HugeParamsBase):
         for vertex_id in edge_ids:
             url += f"ids={vertex_id}&"
         url = url.rstrip("&")
-        response = self.session.get(
+        response = self.__session.get(
             url, auth=self._auth, headers=self._headers, timeout=self._timeout
         )
         if response.status_code == 200 and check_if_authorized(response):
@@ -348,5 +373,5 @@ class GraphManager(HugeParamsBase):
             for item in json.loads(response.content)["edges"]:
                 res.append(EdgeData(item))
             return res
-        else:
-            create_exception(response.content)
+        create_exception(response.content)
+        return None
diff --git a/hugegraph-python-client/src/pyhugegraph/api/graphs.py 
b/hugegraph-python-client/src/pyhugegraph/api/graphs.py
index 6d427ad..8212a90 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/graphs.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/graphs.py
@@ -27,33 +27,29 @@ from pyhugegraph.utils.util import check_if_success
 class GraphsManager(HugeParamsBase):
     def __init__(self, graph_instance):
         super().__init__(graph_instance)
-        self.session = self.set_session(HugeSession.new_session())
-
-    def set_session(self, session):
-        self.session = session
-        return session
+        self.__session = HugeSession.new_session()
 
     def close(self):
-        if self.session:
-            self.session.close()
+        if self.__session:
+            self.__session.close()
 
     def get_all_graphs(self):
         url = f"{self._host}/graphs"
-        response = self.session.get(url, auth=self._auth, 
headers=self._headers)
+        response = self.__session.get(url, auth=self._auth, 
headers=self._headers)
         if check_if_success(response, NotFoundError(response.content)):
             return str(response.content)
         return ""
 
     def get_version(self):
         url = f"{self._host}/versions"
-        response = self.session.get(url, auth=self._auth, 
headers=self._headers)
+        response = self.__session.get(url, auth=self._auth, 
headers=self._headers)
         if check_if_success(response, NotFoundError(response.content)):
             return str(response.content)
         return ""
 
     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.__session.get(url, auth=self._auth, 
headers=self._headers)
         if check_if_success(response, NotFoundError(response.content)):
             return str(response.content)
         return ""
@@ -63,14 +59,14 @@ class GraphsManager(HugeParamsBase):
             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)
+        response = self.__session.delete(url, auth=self._auth, 
headers=self._headers)
         if check_if_success(response, NotFoundError(response.content)):
             return str(response.content)
         return ""
 
     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.__session.get(url, auth=self._auth, 
headers=self._headers)
         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 daa22f1..5726075 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/gremlin.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/gremlin.py
@@ -28,15 +28,11 @@ from pyhugegraph.utils.util import check_if_success
 class GremlinManager(HugeParamsBase):
     def __init__(self, graph_instance):
         super().__init__(graph_instance)
-        self.session = self.set_session(HugeSession.new_session())
-
-    def set_session(self, session):
-        self.session = session
-        return session
+        self.__session = HugeSession.new_session()
 
     def close(self):
-        if self.session:
-            self.session.close()
+        if self.__session:
+            self.__session.close()
 
     def exec(self, gremlin):
         url = f"{self._host}/gremlin"
@@ -45,14 +41,14 @@ class GremlinManager(HugeParamsBase):
             "graph": self._graph_name,
             "g": "__g_" + self._graph_name,
         }
-        response = self.session.post(
+        response = self.__session.post(
             url,
             data=gremlin_data.to_json(),
             auth=self._auth,
             headers=self._headers,
             timeout=self._timeout,
         )
-        error = NotFoundError(f"Gremlin can't get results: {response.content}")
+        error = NotFoundError(f"Gremlin can't get results: 
{str(response.content)}")
         if check_if_success(response, error):
             return ResponseData(json.loads(response.content)).result
         return ""
diff --git a/hugegraph-python-client/src/pyhugegraph/api/metric.py 
b/hugegraph-python-client/src/pyhugegraph/api/metric.py
new file mode 100644
index 0000000..51be7b4
--- /dev/null
+++ b/hugegraph-python-client/src/pyhugegraph/api/metric.py
@@ -0,0 +1,139 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from pyhugegraph.api.common import HugeParamsBase
+from pyhugegraph.utils.exceptions import NotFoundError
+from pyhugegraph.utils.huge_requests import HugeSession
+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()
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        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 10da5b3..2818c5b 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/schema.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/schema.py
@@ -35,29 +35,25 @@ from pyhugegraph.utils.util import check_if_success
 class SchemaManager(HugeParamsBase):
     def __init__(self, graph_instance):
         super().__init__(graph_instance)
-        self.session = self.set_session(HugeSession.new_session())
-
-    def set_session(self, session):
-        self.session = session
-        return session
+        self.__session = HugeSession.new_session()
 
     def close(self):
-        if self.session:
-            self.session.close()
+        if self.__session:
+            self.__session.close()
 
     """
     create schemas, including propertyKey/vertexLabel/edgeLabel/indexLabel
     """
 
     def propertyKey(self, property_name):
-        property_key = PropertyKey(self._graph_instance, self.session)
+        property_key = PropertyKey(self._graph_instance, self.__session)
         property_key.create_parameter_holder()
         property_key.add_parameter("name", property_name)
         property_key.add_parameter("not_exist", True)
         return property_key
 
     def vertexLabel(self, vertex_name):
-        vertex_label = VertexLabel(self._graph_instance, self.session)
+        vertex_label = VertexLabel(self._graph_instance, self.__session)
         vertex_label.create_parameter_holder()
         vertex_label.add_parameter("name", vertex_name)
         # vertex_label.add_parameter("id_strategy", "AUTOMATIC")
@@ -65,101 +61,103 @@ class SchemaManager(HugeParamsBase):
         return vertex_label
 
     def edgeLabel(self, name):
-        edge_label = EdgeLabel(self._graph_instance, self.session)
+        edge_label = EdgeLabel(self._graph_instance, self.__session)
         edge_label.create_parameter_holder()
         edge_label.add_parameter("name", name)
         edge_label.add_parameter("not_exist", True)
         return edge_label
 
     def indexLabel(self, name):
-        index_label = IndexLabel(self._graph_instance, self.session)
+        index_label = IndexLabel(self._graph_instance, self.__session)
         index_label.create_parameter_holder()
         index_label.add_parameter("name", name)
         return index_label
 
-    """
-    create schemas
-    """
-
     def getSchema(self):
         url = f"{self._host}/graphs/{self._graph_name}/schema"
-        response = self.session.get(url, auth=self._auth, 
headers=self._headers)
-        error = NotFoundError(f"schema not found: {response.content}")
+        response = self.__session.get(url, auth=self._auth, 
headers=self._headers)
+        error = NotFoundError(f"schema not found: {str(response.content)}")
         if check_if_success(response, error):
             schema = json.loads(response.content)
             return schema
+        return None
 
     def getPropertyKey(self, property_name):
         url = 
f"{self._host}/graphs/{self._graph_name}/schema/propertykeys/{property_name}"
-        response = self.session.get(url, auth=self._auth, 
headers=self._headers)
-        error = NotFoundError(f"PropertyKey not found: {response.content}")
+        response = self.__session.get(url, auth=self._auth, 
headers=self._headers)
+        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
 
     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.__session.get(url, auth=self._auth, 
headers=self._headers)
         res = []
         if check_if_success(response):
             for item in json.loads(response.content)["propertykeys"]:
                 res.append(PropertyKeyData(item))
             return res
+        return None
 
     def getVertexLabel(self, name):
         url = 
f"{self._host}/graphs/{self._graph_name}/schema/vertexlabels/{name}"
-        response = self.session.get(url, auth=self._auth, 
headers=self._headers)
-        error = NotFoundError(f"VertexLabel not found: {response.content}")
+        response = self.__session.get(url, auth=self._auth, 
headers=self._headers)
+        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
 
     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.__session.get(url, auth=self._auth, 
headers=self._headers)
         res = []
         if check_if_success(response):
             for item in json.loads(response.content)["vertexlabels"]:
                 res.append(VertexLabelData(item))
-            return res
+        return res
 
     def getEdgeLabel(self, label_name):
         url = 
f"{self._host}/graphs/{self._graph_name}/schema/edgelabels/{label_name}"
-        response = self.session.get(url, auth=self._auth, 
headers=self._headers)
-        error = NotFoundError(f"EdgeLabel not found: {response.content}")
+        response = self.__session.get(url, auth=self._auth, 
headers=self._headers)
+        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
 
     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.__session.get(url, auth=self._auth, 
headers=self._headers)
         res = []
         if check_if_success(response):
             for item in json.loads(response.content)["edgelabels"]:
                 res.append(EdgeLabelData(item))
-            return res
+        return res
 
     def getRelations(self):
         url = f"{self._host}/graphs/{self._graph_name}/schema/edgelabels"
-        response = self.session.get(url, auth=self._auth, 
headers=self._headers)
+        response = self.__session.get(url, auth=self._auth, 
headers=self._headers)
         res = []
         if check_if_success(response):
             for item in json.loads(response.content)["edgelabels"]:
                 res.append(EdgeLabelData(item).relations())
-            return res
+        return res
 
     def getIndexLabel(self, name):
         url = 
f"{self._host}/graphs/{self._graph_name}/schema/indexlabels/{name}"
-        response = self.session.get(url, auth=self._auth, 
headers=self._headers)
-        error = NotFoundError(f"EdgeLabel not found: {response.content}")
+        response = self.__session.get(url, auth=self._auth, 
headers=self._headers)
+        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
 
     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.__session.get(url, auth=self._auth, 
headers=self._headers)
         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 78cbcb5..f694a49 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
@@ -26,7 +26,7 @@ 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
+        self.__session = session
 
     @decorator_params
     def link(self, source_label, target_label):
@@ -83,9 +83,12 @@ class EdgeLabel(HugeParamsBase):
 
     @decorator_params
     def ifNotExist(self):
-        url = 
f'{self._host}/graphs/{self._graph_name}/schema/edgelabels/{self._parameter_holder.get_value("name")}'
+        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)
+        response = self.__session.get(url, auth=self._auth, 
headers=self._headers)
         if response.status_code == 200 and check_if_authorized(response):
             self._parameter_holder.set("not_exist", False)
         return self
@@ -109,7 +112,7 @@ class EdgeLabel(HugeParamsBase):
             if key in dic:
                 data[key] = dic[key]
         url = f"{self._host}/graphs/{self._graph_name}/schema/edgelabels"
-        response = self.session.post(
+        response = self.__session.post(
             url, data=json.dumps(data), auth=self._auth, headers=self._headers
         )
         self.clean_parameter_holder()
@@ -118,17 +121,22 @@ class EdgeLabel(HugeParamsBase):
         )
         if check_if_success(response, error):
             return f'create EdgeLabel success, Detail: 
"{str(response.content)}"'
+        return None
 
     @decorator_params
     def remove(self):
-        url = 
f'{self._host}/graphs/{self._graph_name}/schema/edgelabels/{self._parameter_holder.get_value("name")}'
-        response = self.session.delete(url, auth=self._auth, 
headers=self._headers)
+        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)
         self.clean_parameter_holder()
         error = RemoveError(
             f'RemoveError: "remove EdgeLabel failed", Detail:  
"{str(response.content)}"'
         )
         if check_if_success(response, error):
             return f'remove EdgeLabel success, Detail: 
"{str(response.content)}"'
+        return None
 
     @decorator_params
     def append(self):
@@ -142,7 +150,7 @@ class EdgeLabel(HugeParamsBase):
         url = (
             
f'{self._host}/graphs/{self._graph_name}/schema/edgelabels/{data["name"]}?action=append'
         )
-        response = self.session.put(
+        response = self.__session.put(
             url, data=json.dumps(data), auth=self._auth, headers=self._headers
         )
         self.clean_parameter_holder()
@@ -151,6 +159,7 @@ class EdgeLabel(HugeParamsBase):
         )
         if check_if_success(response, error):
             return f'append EdgeLabel success, Detail: 
"{str(response.content)}"'
+        return None
 
     @decorator_params
     def eliminate(self):
@@ -162,7 +171,7 @@ class EdgeLabel(HugeParamsBase):
         )
         url = 
f"{self._host}/graphs/{self._graph_name}/schema/edgelabels/{name}?action=eliminate"
         data = {"name": name, "user_data": user_data}
-        response = self.session.put(
+        response = self.__session.put(
             url, data=json.dumps(data), auth=self._auth, headers=self._headers
         )
         self.clean_parameter_holder()
@@ -171,3 +180,4 @@ class EdgeLabel(HugeParamsBase):
         )
         if check_if_success(response, error):
             return f'eliminate EdgeLabel success, Detail: 
"{str(response.content)}"'
+        return None
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 9ac3829..8eeb437 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
@@ -17,7 +17,6 @@
 
 import json
 
-import requests
 
 from pyhugegraph.api.common import HugeParamsBase
 from pyhugegraph.utils.huge_decorator import decorator_params, decorator_create
@@ -28,7 +27,7 @@ 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
+        self.__session = session
 
     @decorator_params
     def onV(self, vertex_label):
@@ -68,8 +67,11 @@ class IndexLabel(HugeParamsBase):
 
     @decorator_params
     def ifNotExist(self):
-        url = 
f'{self._host}/graphs/{self._graph_name}/schema/indexlabels/{self._parameter_holder.get_value("name")}'
-        response = self.session.get(url, auth=self._auth, 
headers=self._headers)
+        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)
         if response.status_code == 200 and check_if_authorized(response):
             self._parameter_holder.set("not_exist", False)
         return self
@@ -84,7 +86,7 @@ class IndexLabel(HugeParamsBase):
         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(
+        response = self.__session.post(
             url, data=json.dumps(data), auth=self._auth, headers=self._headers
         )
         self.clean_parameter_holder()
@@ -93,15 +95,17 @@ class IndexLabel(HugeParamsBase):
         )
         if check_if_success(response, error):
             return f'create IndexLabel success, Deatil: 
"{str(response.content)}"'
+        return None
 
     @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)
+        response = self.__session.delete(url, auth=self._auth, 
headers=self._headers)
         self.clean_parameter_holder()
         error = RemoveError(
             f'RemoveError: "remove IndexLabel failed", Detail 
"{str(response.content)}"'
         )
         if check_if_success(response, error):
             return f'remove IndexLabel success, Deatil: 
"{str(response.content)}"'
+        return None
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 d0ce9a1..c0a3af4 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
@@ -17,7 +17,6 @@
 
 import json
 
-import requests
 
 from pyhugegraph.api.common import HugeParamsBase
 from pyhugegraph.utils.exceptions import CreateError, UpdateError, RemoveError
@@ -28,7 +27,7 @@ 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
+        self.__session = session
 
     @decorator_params
     def asInt(self):
@@ -98,8 +97,11 @@ class PropertyKey(HugeParamsBase):
         return self
 
     def ifNotExist(self):
-        url = 
f'{self._host}/graphs/{self._graph_name}/schema/propertykeys/{self._parameter_holder.get_value("name")}'
-        response = self.session.get(url, auth=self._auth, 
headers=self._headers)
+        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)
         if response.status_code == 200 and check_if_authorized(response):
             self._parameter_holder.set("not_exist", False)
         return self
@@ -113,15 +115,18 @@ class PropertyKey(HugeParamsBase):
         if "cardinality" in dic:
             property_keys["cardinality"] = dic["cardinality"]
         url = f"{self._host}/graphs/{self._graph_name}/schema/propertykeys"
-        response = self.session.post(
+        response = self.__session.post(
             url, data=json.dumps(property_keys), auth=self._auth, 
headers=self._headers
         )
         self.clean_parameter_holder()
         if check_if_success(
             response,
-            CreateError(f'CreateError: "create PropertyKey failed", Detail: 
{response.content}'),
+            CreateError(
+                f'CreateError: "create PropertyKey failed", Detail: 
{str(response.content)}'
+            ),
         ):
-            return f"create PropertyKey success, Detail: {response.content}"
+            return f"create PropertyKey success, Detail: 
{str(response.content)}"
+        return f"create PropertyKey failed, Detail: {str(response.content)}"
 
     @decorator_params
     def append(self):
@@ -131,16 +136,22 @@ class PropertyKey(HugeParamsBase):
             user_data = {}
         data = {"name": property_name, "user_data": user_data}
 
-        url = 
f"{self._host}/graphs/{self._graph_name}/schema/propertykeys/{property_name}/?action=append"
-        response = self.session.put(
+        url = (
+            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
         )
         self.clean_parameter_holder()
         if check_if_success(
             response,
-            UpdateError(f'UpdateError: "append PropertyKey failed", Detail: 
{response.content}'),
+            UpdateError(
+                f'UpdateError: "append PropertyKey failed", Detail: 
{str(response.content)}'
+            ),
         ):
-            return f"append PropertyKey success, Detail: {response.content}"
+            return f"append PropertyKey success, Detail: 
{str(response.content)}"
+        return f"append PropertyKey failed, Detail: {str(response.content)}"
 
     @decorator_params
     def eliminate(self):
@@ -150,8 +161,11 @@ class PropertyKey(HugeParamsBase):
             user_data = {}
         data = {"name": property_name, "user_data": user_data}
 
-        url = 
f"{self._host}/graphs/{self._graph_name}/schema/propertykeys/{property_name}/?action=eliminate"
-        response = self.session.put(
+        url = (
+            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
         )
         self.clean_parameter_holder()
@@ -160,12 +174,13 @@ class PropertyKey(HugeParamsBase):
         )
         if check_if_success(response, error):
             return f"eliminate PropertyKey success, Detail: 
{str(response.content)}"
+        return f"eliminate PropertyKey failed, Detail: {str(response.content)}"
 
     @decorator_params
     def remove(self):
         dic = self._parameter_holder.get_dic()
         url = 
f'{self._host}/graphs/{self._graph_name}/schema/propertykeys/{dic["name"]}'
-        response = self.session.delete(url)
+        response = self.__session.delete(url)
         self.clean_parameter_holder()
         if check_if_success(
             response,
@@ -174,3 +189,4 @@ class PropertyKey(HugeParamsBase):
             ),
         ):
             return f'delete PropertyKey success, Detail: {dic["name"]}'
+        return f"delete PropertyKey failed, Detail: {str(response.content)}"
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 3a45cff..0274ad6 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
@@ -17,8 +17,6 @@
 
 import json
 
-import requests
-
 from pyhugegraph.api.common import HugeParamsBase
 from pyhugegraph.utils.exceptions import CreateError, UpdateError, RemoveError
 from pyhugegraph.utils.huge_decorator import decorator_params, decorator_create
@@ -28,7 +26,7 @@ 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
+        self.__session = session
 
     @decorator_params
     def useAutomaticId(self):
@@ -82,9 +80,12 @@ class VertexLabel(HugeParamsBase):
         return self
 
     def ifNotExist(self):
-        url = 
f'{self._host}/graphs/{self._graph_name}/schema/vertexlabels/{self._parameter_holder.get_value("name")}'
+        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)
+        response = self.__session.get(url, auth=self._auth, 
headers=self._headers)
         if response.status_code == 200 and check_if_authorized(response):
             self._parameter_holder.set("not_exist", False)
         return self
@@ -107,7 +108,7 @@ class VertexLabel(HugeParamsBase):
             if key in dic:
                 data[key] = dic[key]
         url = f"{self._host}/graphs/{self._graph_name}/schema/vertexlabels"
-        response = self.session.post(
+        response = self.__session.post(
             url, data=json.dumps(data), auth=self._auth, headers=self._headers
         )
         self.clean_parameter_holder()
@@ -116,6 +117,7 @@ class VertexLabel(HugeParamsBase):
         )
         if check_if_success(response, error):
             return f'create VertexLabel success, Detail: 
"{str(response.content)}"'
+        return f'create VertexLabel failed, Detail: "{str(response.content)}"'
 
     @decorator_params
     def append(self):
@@ -123,7 +125,10 @@ 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}/schema/vertexlabels/{dic["name"]}?action=append'
+        url = (
+            f"{self._host}/graphs/{self._graph_name}"
+            f'/schema/vertexlabels/{dic["name"]}?action=append'
+        )
 
         data = {
             "name": dic["name"],
@@ -131,7 +136,7 @@ class VertexLabel(HugeParamsBase):
             "nullable_keys": nullable_keys,
             "user_data": user_data,
         }
-        response = self.session.put(
+        response = self.__session.put(
             url, data=json.dumps(data), auth=self._auth, headers=self._headers
         )
         self.clean_parameter_holder()
@@ -140,18 +145,20 @@ class VertexLabel(HugeParamsBase):
         )
         if check_if_success(response, error):
             return f'append VertexLabel success, Detail: 
"{str(response.content)}"'
+        return f'append VertexLabel failed, Detail: "{str(response.content)}"'
 
     @decorator_params
     def remove(self):
         name = self._parameter_holder.get_value("name")
         url = 
f"{self._host}/graphs/{self._graph_name}/schema/vertexlabels/{name}"
-        response = self.session.delete(url, auth=self._auth, 
headers=self._headers)
+        response = self.__session.delete(url, auth=self._auth, 
headers=self._headers)
         self.clean_parameter_holder()
         error = RemoveError(
             f'RemoveError: "remove VertexLabel failed", Detail: 
"{str(response.content)}"'
         )
         if check_if_success(response, error):
             return f'remove VertexLabel success, Detail: 
"{str(response.content)}"'
+        return f'remove VertexLabel failed, Detail: "{str(response.content)}"'
 
     @decorator_params
     def eliminate(self):
@@ -164,7 +171,7 @@ class VertexLabel(HugeParamsBase):
             "name": self._parameter_holder.get_value("name"),
             "user_data": user_data,
         }
-        response = self.session.put(
+        response = self.__session.put(
             url, data=json.dumps(data), auth=self._auth, headers=self._headers
         )
         error = UpdateError(
@@ -172,3 +179,4 @@ class VertexLabel(HugeParamsBase):
         )
         if check_if_success(response, error):
             return f'eliminate VertexLabel success, Detail: 
"{str(response.content)}"'
+        return f'eliminate VertexLabel failed, Detail: 
"{str(response.content)}"'
diff --git a/hugegraph-python-client/src/pyhugegraph/api/variable.py 
b/hugegraph-python-client/src/pyhugegraph/api/task.py
similarity index 55%
copy from hugegraph-python-client/src/pyhugegraph/api/variable.py
copy to hugegraph-python-client/src/pyhugegraph/api/task.py
index cf1549e..fa72540 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/variable.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/task.py
@@ -15,66 +15,58 @@
 # specific language governing permissions and limitations
 # under the License.
 
-import json
-
 from pyhugegraph.api.common import HugeParamsBase
 from pyhugegraph.utils.exceptions import NotFoundError
 from pyhugegraph.utils.huge_requests import HugeSession
 from pyhugegraph.utils.util import check_if_success
 
 
-class VariableManager(HugeParamsBase):
+class TaskManager(HugeParamsBase):
     def __init__(self, graph_instance):
         super().__init__(graph_instance)
-        self.session = self.set_session(HugeSession.new_session())
-
-    def set_session(self, session):
-        self.session = session
-        return session
+        self.__session = HugeSession.new_session()
 
     def close(self):
-        if self.session:
-            self.session.close()
-
-    def set(self, key, value):
-        url = f"{self._host}/graphs/{self._graph_name}/variables/{key}"
-        data = {"data": value}
+        if self.__session:
+            self.__session.close()
 
-        response = self.session.put(
+    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,
-            data=json.dumps(data),
+            params=params,
             auth=self._auth,
             headers=self._headers,
             timeout=self._timeout,
         )
-        if check_if_success(response, NotFoundError(response.content)):
-            return response.json()
-        return {}
-
-    def get(self, key):
-        url = f"{self._host}/graphs/{self._graph_name}/variables/{key}"
+        check_if_success(response, NotFoundError(response.content))
+        return response.json()
 
-        response = self.session.get(
+    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
         )
-        if check_if_success(response, NotFoundError(response.content)):
-            return response.json()
-        return {}
-
-    def all(self):
-        url = f"{self._host}/graphs/{self._graph_name}/variables"
+        check_if_success(response, NotFoundError(response.content))
+        return response.json()
 
-        response = self.session.get(
+    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
         )
-        if check_if_success(response, NotFoundError(response.content)):
-            return response.json()
-        return {}
-
-    def remove(self, key):
-        url = f"{self._host}/graphs/{self._graph_name}/variables/{key}"
+        check_if_success(response, NotFoundError(response.content))
+        return response.status_code
 
-        response = self.session.delete(
+    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
         )
         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
new file mode 100644
index 0000000..b88ea74
--- /dev/null
+++ b/hugegraph-python-client/src/pyhugegraph/api/traverser.py
@@ -0,0 +1,360 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+import json
+
+from pyhugegraph.api.common import HugeParamsBase
+from pyhugegraph.utils.exceptions import NotFoundError
+from pyhugegraph.utils.huge_requests import HugeSession
+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()
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    def multi_node_shortest_path(
+        self,
+        vertices,
+        direction="BOTH",
+        properties=None,
+        max_depth=10,
+        capacity=100000000,
+        with_vertex=True,
+    ):
+        if properties is None:
+            properties = {}
+        url = f"{self.url}/multinodeshortestpath"
+        data = {
+            "vertices": {"ids": vertices},
+            "step": {"direction": direction, "properties": properties},
+            "max_depth": max_depth,
+            "capacity": capacity,
+            "with_vertex": with_vertex,
+        }
+        response = self.__session.post(
+            url,
+            data=json.dumps(data),
+            auth=self._auth,
+            headers=self._headers,
+            timeout=self._timeout,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+            "sort_by": sort_by,
+            "with_vertex": with_vertex,
+            "capacity": capacity,
+            "limit": limit,
+        }
+        response = self.__session.post(
+            url,
+            data=json.dumps(data),
+            auth=self._auth,
+            headers=self._headers,
+            timeout=self._timeout,
+        )
+        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"
+        data = {
+            "sources": sources,
+            "targets": targets,
+            "steps": steps,
+            "capacity": capacity,
+            "limit": limit,
+            "with_vertex": with_vertex,
+        }
+        response = self.__session.post(
+            url,
+            data=json.dumps(data),
+            auth=self._auth,
+            headers=self._headers,
+            timeout=self._timeout,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    def customized_crosspoints(
+        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,
+            "with_path": with_path,
+            "with_vertex": with_vertex,
+            "capacity": capacity,
+            "limit": limit,
+        }
+        response = self.__session.post(
+            url,
+            data=json.dumps(data),
+            auth=self._auth,
+            headers=self._headers,
+            timeout=self._timeout,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    def fusiform_similarity(
+        self,
+        sources,
+        label,
+        direction,
+        min_neighbors,
+        alpha,
+        min_similars,
+        top,
+        group_property,
+        min_groups=2,
+        max_degree=10000,
+        capacity=-1,
+        limit=-1,
+        with_intermediary=False,
+        with_vertex=True,
+    ):
+        url = f"{self.url}/fusiformsimilarity"
+        data = {
+            "sources": sources,
+            "label": label,
+            "direction": direction,
+            "min_neighbors": min_neighbors,
+            "alpha": alpha,
+            "min_similars": min_similars,
+            "top": top,
+            "group_property": group_property,
+            "min_groups": min_groups,
+            "max_degree": max_degree,
+            "capacity": capacity,
+            "limit": limit,
+            "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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        if check_if_success(response, NotFoundError(response.content)):
+            return response.json()
+        return {}
+
+    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,
+        )
+        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 cf1549e..2345bcd 100644
--- a/hugegraph-python-client/src/pyhugegraph/api/variable.py
+++ b/hugegraph-python-client/src/pyhugegraph/api/variable.py
@@ -26,21 +26,17 @@ from pyhugegraph.utils.util import check_if_success
 class VariableManager(HugeParamsBase):
     def __init__(self, graph_instance):
         super().__init__(graph_instance)
-        self.session = self.set_session(HugeSession.new_session())
-
-    def set_session(self, session):
-        self.session = session
-        return session
+        self.__session = HugeSession.new_session()
 
     def close(self):
-        if self.session:
-            self.session.close()
+        if self.__session:
+            self.__session.close()
 
     def set(self, key, value):
         url = f"{self._host}/graphs/{self._graph_name}/variables/{key}"
         data = {"data": value}
 
-        response = self.session.put(
+        response = self.__session.put(
             url,
             data=json.dumps(data),
             auth=self._auth,
@@ -54,7 +50,7 @@ class VariableManager(HugeParamsBase):
     def get(self, key):
         url = f"{self._host}/graphs/{self._graph_name}/variables/{key}"
 
-        response = self.session.get(
+        response = self.__session.get(
             url, auth=self._auth, headers=self._headers, timeout=self._timeout
         )
         if check_if_success(response, NotFoundError(response.content)):
@@ -64,7 +60,7 @@ class VariableManager(HugeParamsBase):
     def all(self):
         url = f"{self._host}/graphs/{self._graph_name}/variables"
 
-        response = self.session.get(
+        response = self.__session.get(
             url, auth=self._auth, headers=self._headers, timeout=self._timeout
         )
         if check_if_success(response, NotFoundError(response.content)):
@@ -74,7 +70,7 @@ class VariableManager(HugeParamsBase):
     def remove(self, key):
         url = f"{self._host}/graphs/{self._graph_name}/variables/{key}"
 
-        response = self.session.delete(
+        response = self.__session.delete(
             url, auth=self._auth, headers=self._headers, timeout=self._timeout
         )
         check_if_success(response, NotFoundError(response.content))
diff --git a/hugegraph-python-client/src/pyhugegraph/client.py 
b/hugegraph-python-client/src/pyhugegraph/client.py
index 3972af0..2398f7f 100644
--- a/hugegraph-python-client/src/pyhugegraph/client.py
+++ b/hugegraph-python-client/src/pyhugegraph/client.py
@@ -14,12 +14,15 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
+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
+from pyhugegraph.api.metric import MetricsManager
 from pyhugegraph.api.schema import SchemaManager
+from pyhugegraph.api.task import TaskManager
+from pyhugegraph.api.traverser import TraverserManager
 from pyhugegraph.api.variable import VariableManager
 from pyhugegraph.structure.graph_instance import GraphInstance
 
@@ -33,33 +36,43 @@ class PyHugeClient(HugeParamsBase):
         self._graphs = None
         self._gremlin = None
         self._variable = None
+        self._auth = None
+        self._task = None
+        self._metrics = None
+        self._traverser = None
 
     def schema(self):
-        if self._schema:
-            return self._schema
-        self._schema = SchemaManager(self._graph_instance)
+        self._schema = self._schema or SchemaManager(self._graph_instance)
         return self._schema
 
     def gremlin(self):
-        if self._gremlin:
-            return self._gremlin
-        self._gremlin = GremlinManager(self._graph_instance)
+        self._gremlin = self._gremlin or GremlinManager(self._graph_instance)
         return self._gremlin
 
     def graph(self):
-        if self._graph:
-            return self._graph
-        self._graph = GraphManager(self._graph_instance)
+        self._graph = self._graph or GraphManager(self._graph_instance)
         return self._graph
 
     def graphs(self):
-        if self._graphs:
-            return self._graphs
-        self._graphs = GraphsManager(self._graph_instance)
+        self._graphs = self._graphs or GraphsManager(self._graph_instance)
         return self._graphs
 
     def variable(self):
-        if self._variable:
-            return self._variable
-        self._variable = VariableManager(self._graph_instance)
+        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
diff --git 
a/hugegraph-python-client/src/pyhugegraph/structure/edge_label_data.py 
b/hugegraph-python-client/src/pyhugegraph/structure/edge_label_data.py
index 48eb9e4..b0ba5a2 100644
--- a/hugegraph-python-client/src/pyhugegraph/structure/edge_label_data.py
+++ b/hugegraph-python-client/src/pyhugegraph/structure/edge_label_data.py
@@ -70,6 +70,14 @@ class EdgeLabelData:
         res = f"{self.__source_label}--{self.__name}-->{self.__target_label}"
         return res
 
+    @property
+    def indexLabels(self):
+        return self.__index_labels
+
+    @property
+    def enableLabelIndex(self):
+        return self.__enable_label_index
+
     def __repr__(self):
         res = f"name: {self.__name}, properties: {self.__properties}"
         return res
diff --git 
a/hugegraph-python-client/src/pyhugegraph/structure/vertex_label_data.py 
b/hugegraph-python-client/src/pyhugegraph/structure/vertex_label_data.py
index 2a8e443..39da4ee 100644
--- a/hugegraph-python-client/src/pyhugegraph/structure/vertex_label_data.py
+++ b/hugegraph-python-client/src/pyhugegraph/structure/vertex_label_data.py
@@ -56,6 +56,14 @@ class VertexLabelData:
     def userdata(self):
         return self.__user_data
 
+    @property
+    def indexLabels(self):
+        return self.__index_labels
+
+    @property
+    def enableLabelIndex(self):
+        return self.__enable_label_index
+
     def __repr__(self):
         res = (
             f"name: {self.__name}, primary_keys: {self.__primary_keys}, "
diff --git a/hugegraph-python-client/src/pyhugegraph/utils/huge_decorator.py 
b/hugegraph-python-client/src/pyhugegraph/utils/huge_decorator.py
index 47906ad..b7151f3 100644
--- a/hugegraph-python-client/src/pyhugegraph/utils/huge_decorator.py
+++ b/hugegraph-python-client/src/pyhugegraph/utils/huge_decorator.py
@@ -41,5 +41,5 @@ def decorator_create(func, *args, **kwargs):
 def decorator_auth(func, *args, **kwargs):
     response = args[0]
     if response.status_code == 401:
-        raise NotAuthorizedError(f"NotAuthorized: {response.content}")
+        raise NotAuthorizedError(f"NotAuthorized: {str(response.content)}")
     return func(*args, **kwargs)
diff --git a/hugegraph-python-client/src/pyhugegraph/utils/util.py 
b/hugegraph-python-client/src/pyhugegraph/utils/util.py
index 56d6533..e07dec3 100644
--- a/hugegraph-python-client/src/pyhugegraph/utils/util.py
+++ b/hugegraph-python-client/src/pyhugegraph/utils/util.py
@@ -36,7 +36,9 @@ def create_exception(response_content):
 
 def check_if_authorized(response):
     if response.status_code == 401:
-        raise NotAuthorizedError(f"Please check your username and password. 
{response.content}")
+        raise NotAuthorizedError(
+            f"Please check your username and password. {str(response.content)}"
+        )
     return True
 
 
diff --git a/hugegraph-python-client/src/tests/api/test_auth.py 
b/hugegraph-python-client/src/tests/api/test_auth.py
new file mode 100644
index 0000000..10e6bad
--- /dev/null
+++ b/hugegraph-python-client/src/tests/api/test_auth.py
@@ -0,0 +1,209 @@
+# 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 unittest
+
+from pyhugegraph.utils.exceptions import NotFoundError
+from tests.client_utils import ClientUtils
+
+
+class TestAuthManager(unittest.TestCase):
+    client = None
+    auth = None
+
+    @classmethod
+    def setUpClass(cls):
+        cls.client = ClientUtils()
+        cls.auth = cls.client.auth
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.client.clear_graph_all_data()
+
+    def setUp(self):
+        users = self.auth.list_users()
+        for user in users["users"]:
+            if user["user_creator"] != "system":
+                self.auth.delete_user(user["id"])
+
+        groups = self.auth.list_groups()
+        for group in groups["groups"]:
+            self.auth.delete_group(group["id"])
+
+        belongs = self.auth.list_belongs()
+        for belong in belongs["belongs"]:
+            self.auth.delete_belong(belong["id"])
+
+        targets = self.auth.list_targets()
+        for target in targets["targets"]:
+            self.auth.delete_target(target["id"])
+
+        accesses = self.auth.list_accesses()
+        for access in accesses["accesses"]:
+            self.auth.revoke_accesses(access["id"])
+
+    def tearDown(self):
+        pass
+
+    def test_user_operations(self):
+        users = self.auth.list_users()
+        self.assertTrue(users["users"][0]["user_creator"] == "system")
+
+        # {'user_password': '',
+        # 'user_update': '2024-01-26 02:45:57.317', 'user_name': 'test_user',
+        # 'user_creator': 'admin', 'id': '-30:test_user', 'user_create': 
'2024-01-26 02:45:57.317'}
+        user = self.auth.create_user("test_user", "password")
+        self.assertEqual(user["user_name"], "test_user")
+
+        user = self.auth.get_user(user["id"])
+        self.assertEqual(user["user_name"], "test_user")
+
+        # Modify the user
+        user = self.auth.modify_user(user["id"], 
user_email="[email protected]")
+        self.assertEqual(user["user_email"], "[email protected]")
+
+        # Delete the user
+        self.auth.delete_user(user["id"])
+        # Verify the user was deleted
+        try:
+            user = self.auth.get_user(user["id"])
+        except NotFoundError as e:
+            self.assertTrue(f"Can\\'t find user with id \\'{user['id']}\\'" in 
str(e))
+
+    def test_group_operations(self):
+        # Create a group
+        group = self.auth.create_group("test_group")
+        self.assertEqual(group["group_name"], "test_group")
+
+        groups = self.auth.list_groups()
+        self.assertEqual(groups["groups"][0]["group_name"], "test_group")
+
+        # Get the group
+        group = self.auth.get_group(group["id"])
+        self.assertEqual(group["group_name"], "test_group")
+
+        # Modify the group
+        group = self.auth.modify_group(group["id"], 
group_description="test_description")
+        self.assertEqual(group["group_description"], "test_description")
+
+        # Delete the group
+        self.auth.delete_group(group["id"])
+        # Verify the group was deleted
+        try:
+            group = self.auth.get_group(group["id"])
+        except NotFoundError as e:
+            self.assertTrue(f"Can\\'t find group with id \\'{group['id']}\\'" 
in str(e))
+
+    def test_target_operations(self):
+        # Create a target
+        target = self.auth.create_target(
+            "test_target",
+            "graph1",
+            "127.0.0.1:8080",
+            [{"type": "VERTEX", "label": "person", "properties": {"city": 
"Beijing"}}],
+        )
+        # Verify the target was created
+        self.assertEqual(target["target_name"], "test_target")
+
+        # Get the target
+        target = self.auth.get_target(target["id"])
+        self.assertEqual(target["target_name"], "test_target")
+
+        # Modify the target
+        target = self.auth.update_target(
+            target["id"],
+            "test_target",
+            "graph1",
+            "127.0.0.1:8080",
+            [{"type": "VERTEX", "label": "person", "properties": {"city": 
"Shanghai"}}],
+        )
+        # Verify the target was modified
+        self.assertEqual(target["target_resources"][0]["properties"]["city"], 
"Shanghai")
+
+        # Delete the target
+        self.auth.delete_target(target["id"])
+        # Verify the target was deleted
+        with self.assertRaises(Exception):
+            self.auth.get_target(target["id"])
+
+    def test_belong_operations(self):
+        user = self.auth.create_user("all", "password")
+        group = self.auth.create_group("all")
+
+        # Create a belong
+        # {'belong_create': '2024-01-29 02:04:41.161', 'belong_creator': 
'admin',
+        # 'belong_update': '2024-01-29 02:04:41.161', 'id': 
'S-30:all>-49>>S-36:all',
+        # 'user': '-30:all', 'group': '-36:all'}
+        belong = self.auth.create_belong(user["id"], group["id"])
+        # Verify the belong was created
+        self.assertEqual(belong["user"], user["id"])
+        self.assertEqual(belong["group"], group["id"])
+
+        belongs = self.auth.list_belongs()
+        self.assertEqual(belongs["belongs"][0]["user"], user["id"])
+
+        # Get the belong
+        belong = self.auth.get_belong(belong["id"])
+        self.assertEqual(belong["user"], user["id"])
+        self.assertEqual(belong["group"], group["id"])
+
+        # Modify the belong
+        belong = self.auth.update_belong(belong["id"], "WRITE")
+        # Verify the belong was modified
+        self.assertEqual(belong["belong_description"], "WRITE")
+
+        # Delete the belong
+        self.auth.delete_belong(belong["id"])
+        # Verify the belong was deleted
+        with self.assertRaises(Exception):
+            self.auth.get_belong(belong["id"])
+
+    def test_access_operations(self):
+        # Create a permission
+        group = self.auth.create_group("test_group")
+        target = self.auth.create_target(
+            "test_target",
+            "graph1",
+            "127.0.0.1:8080",
+            [{"type": "VERTEX", "label": "person", "properties": {"city": 
"Beijing"}}],
+        )
+        access = self.auth.grant_accesses(group["id"], target["id"], "READ")
+        # Verify the permission was created
+        self.assertEqual(access["group"], group["id"])
+        self.assertEqual(access["target"], target["id"])
+        self.assertEqual(access["access_permission"], "READ")
+
+        accesses = self.auth.list_accesses()
+        self.assertEqual(accesses["accesses"][0]["group"], group["id"])
+
+        # Get the permission
+        access = self.auth.get_accesses(access["id"])
+        self.assertEqual(access["group"], group["id"])
+        self.assertEqual(access["target"], target["id"])
+        self.assertEqual(access["access_permission"], "READ")
+
+        # Modify the permission
+        access = self.auth.modify_accesses(access["id"], "test_description")
+        # Verify the permission was modified
+        self.assertEqual(access["access_description"], "test_description")
+
+        # Delete the permission
+        self.auth.revoke_accesses(access["id"])
+        # Verify the permission was deleted
+        with self.assertRaises(Exception):
+            self.auth.get_accesses(access["id"])
diff --git a/hugegraph-python-client/src/tests/api/test_graph.py 
b/hugegraph-python-client/src/tests/api/test_graph.py
new file mode 100644
index 0000000..9c8aac7
--- /dev/null
+++ b/hugegraph-python-client/src/tests/api/test_graph.py
@@ -0,0 +1,161 @@
+# 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 unittest
+
+from pyhugegraph.utils.exceptions import NotFoundError
+from tests.client_utils import ClientUtils
+
+
+class TestGraphManager(unittest.TestCase):
+    client = None
+    graph = None
+
+    @classmethod
+    def setUpClass(cls):
+        cls.client = ClientUtils()
+        cls.graph = cls.client.graph
+        cls.client.init_property_key()
+        cls.client.init_vertex_label()
+        cls.client.init_edge_label()
+        cls.client.init_index_label()
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.client.clear_graph_all_data()
+
+    def test_add_vertex(self):
+        vertex = self.graph.addVertex("person", {"name": "marko", "age": 29, 
"city": "Beijing"})
+        self.assertIsNotNone(vertex)
+
+    def test_add_vertices(self):
+        vertices = self.graph.addVertices(
+            [
+                ("person", {"name": "vadas", "age": 27, "city": "Hongkong"}),
+                ("person", {"name": "marko", "age": 29, "city": "Beijing"}),
+            ]
+        )
+        self.assertEqual(len(vertices), 2)
+
+    def test_append_vertex(self):
+        vertex = self.graph.addVertex("person", {"name": "Alice", "age": 20})
+        appended_vertex = self.graph.appendVertex(vertex.id, {"city": 
"Beijing"})
+        self.assertEqual(appended_vertex.properties["city"], "Beijing")
+
+    def test_eliminate_vertex(self):
+        vertex = self.graph.addVertex("person", {"name": "marko", "age": 29, 
"city": "Beijing"})
+        self.graph.eliminateVertex(vertex.id, {"city": "Beijing"})
+        eliminated_vertex = self.graph.getVertexById(vertex.id)
+        self.assertIsNone(eliminated_vertex.properties.get("city"))
+
+    def test_get_vertex_by_id(self):
+        vertex = self.graph.addVertex("person", {"name": "Alice", "age": 20})
+        retrieved_vertex = self.graph.getVertexById(vertex.id)
+        self.assertEqual(retrieved_vertex.id, vertex.id)
+
+    def test_get_vertex_by_page(self):
+        self.graph.addVertex("person", {"name": "Alice", "age": 20})
+        self.graph.addVertex("person", {"name": "Bob", "age": 23})
+        vertices = self.graph.getVertexByPage("person", 1)
+        self.assertEqual(len(vertices), 2)
+
+    def test_get_vertex_by_condition(self):
+        self.graph.addVertex("person", {"name": "Alice", "age": 25})
+        self.graph.addVertex("person", {"name": "Bob", "age": 30})
+        vertices = self.graph.getVertexByCondition("person", 
properties={"age": "P.gt(29)"})
+        self.assertEqual(len(vertices), 1)
+        self.assertEqual(vertices[0].properties["name"], "Bob")
+
+    def test_remove_vertex_by_id(self):
+        vertex = self.graph.addVertex("person", {"name": "Alice", "age": 20})
+        self.graph.removeVertexById(vertex.id)
+        try:
+            self.graph.getVertexById(vertex.id)
+        except NotFoundError as e:
+            self.assertTrue("Alice\\' does not exist" in str(e))
+
+    def test_add_edge(self):
+        vertex1 = self.graph.addVertex("person", {"name": "Alice", "age": 20})
+        vertex2 = self.graph.addVertex("person", {"name": "Bob", "age": 23})
+        edge = self.graph.addEdge("knows", vertex1.id, vertex2.id, {"date": 
"2012-01-10"})
+        self.assertIsNotNone(edge)
+
+    def test_add_edges(self):
+        vertex1 = self.graph.addVertex("person", {"name": "Alice", "age": 20})
+        vertex2 = self.graph.addVertex("person", {"name": "Bob", "age": 23})
+
+        vertices = self.graph.addEdges(
+            [
+                ("knows", vertex1.id, vertex2.id, "person", "person", {"date": 
"2012-01-10"}),
+                ("knows", vertex2.id, vertex1.id, "person", "person", {"date": 
"2012-01-10"}),
+            ]
+        )
+        self.assertEqual(len(vertices), 2)
+
+    def test_append_edge(self):
+        vertex1 = self.graph.addVertex("person", {"name": "Alice", "age": 20})
+        vertex2 = self.graph.addVertex("person", {"name": "Bob", "age": 23})
+        edge = self.graph.addEdge("knows", vertex1.id, vertex2.id, {"date": 
"2012-01-10"})
+        appended_edge = self.graph.appendEdge(edge.id, {"city": "Beijing"})
+        self.assertEqual(appended_edge.properties["city"], "Beijing")
+
+    def test_eliminate_edge(self):
+        vertex1 = self.graph.addVertex("person", {"name": "Alice", "age": 20})
+        vertex2 = self.graph.addVertex("person", {"name": "Bob", "age": 23})
+        edge = self.graph.addEdge("knows", vertex1.id, vertex2.id, {"date": 
"2012-01-10"})
+        self.graph.eliminateEdge(edge.id, {"city": "Beijing"})
+        eliminated_edge = self.graph.getEdgeById(edge.id)
+        self.assertIsNone(eliminated_edge.properties.get("city"))
+
+    def test_get_edge_by_id(self):
+        vertex1 = self.graph.addVertex("person", {"name": "Alice", "age": 20})
+        vertex2 = self.graph.addVertex("person", {"name": "Bob", "age": 23})
+        edge = self.graph.addEdge("knows", vertex1.id, vertex2.id, {"date": 
"2012-01-10"})
+        retrieved_edge = self.graph.getEdgeById(edge.id)
+        self.assertEqual(retrieved_edge.id, edge.id)
+
+    def test_get_edge_by_page(self):
+        vertex1 = self.graph.addVertex("person", {"name": "Alice", "age": 20})
+        vertex2 = self.graph.addVertex("person", {"name": "Bob", "age": 23})
+        self.graph.addEdge("knows", vertex1.id, vertex2.id, {"date": 
"2012-01-10"})
+        self.graph.addEdge("knows", vertex2.id, vertex1.id, {"date": 
"2012-01-10"})
+        edges = self.graph.getEdgeByPage("knows")
+        self.assertEqual(len(edges), 2)
+
+    def test_remove_edge_by_id(self):
+        vertex1 = self.graph.addVertex("person", {"name": "Alice", "age": 20})
+        vertex2 = self.graph.addVertex("person", {"name": "Bob", "age": 23})
+        edge = self.graph.addEdge("knows", vertex1.id, vertex2.id, {"date": 
"2012-01-10"})
+        self.graph.removeEdgeById(edge.id)
+        try:
+            self.graph.getEdgeById(edge.id)
+        except NotFoundError as e:
+            self.assertTrue("does not exist" in str(e))
+
+    def test_get_vertices_by_id(self):
+        vertex1 = self.graph.addVertex("person", {"name": "Alice", "age": 20})
+        vertex2 = self.graph.addVertex("person", {"name": "Bob", "age": 23})
+        vertices = self.graph.getVerticesById([vertex1.id, vertex2.id])
+        self.assertEqual(len(vertices), 2)
+
+    def test_get_edges_by_id(self):
+        vertex1 = self.graph.addVertex("person", {"name": "Alice", "age": 20})
+        vertex2 = self.graph.addVertex("person", {"name": "Bob", "age": 23})
+        edge1 = self.graph.addEdge("knows", vertex1.id, vertex2.id, {"date": 
"2012-01-10"})
+        edge2 = self.graph.addEdge("knows", vertex2.id, vertex1.id, {"date": 
"2012-01-10"})
+        edges = self.graph.getEdgesById([edge1.id, edge2.id])
+        self.assertEqual(len(edges), 2)
diff --git a/hugegraph-python-client/src/tests/api/test_graphs.py 
b/hugegraph-python-client/src/tests/api/test_graphs.py
new file mode 100644
index 0000000..d34a971
--- /dev/null
+++ b/hugegraph-python-client/src/tests/api/test_graphs.py
@@ -0,0 +1,60 @@
+# 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 unittest
+
+from tests.client_utils import ClientUtils
+
+
+class TestGraphsManager(unittest.TestCase):
+    client = None
+    graph = None
+
+    @classmethod
+    def setUpClass(cls):
+        cls.client = ClientUtils()
+        cls.graphs = cls.client.graphs
+        cls.client.init_property_key()
+        cls.client.init_vertex_label()
+        cls.client.init_edge_label()
+        cls.client.init_index_label()
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.client.clear_graph_all_data()
+
+    def setUp(self):
+        pass
+
+    def tearDown(self):
+        pass
+
+    def test_get_all_graphs(self):
+        all_graphs = self.graphs.get_all_graphs()
+        self.assertTrue("hugegraph" in all_graphs)
+
+    def test_get_version(self):
+        version = self.graphs.get_version()
+        self.assertIsNotNone(version)
+
+    def test_get_graph_info(self):
+        graph_info = self.graphs.get_graph_info()
+        self.assertTrue("backend" in graph_info)
+
+    def test_get_graph_config(self):
+        graph_config = self.graphs.get_graph_config()
+        self.assertIsNotNone(graph_config)
diff --git a/hugegraph-python-client/src/tests/api/test_gremlin.py 
b/hugegraph-python-client/src/tests/api/test_gremlin.py
index 8bd6389..3987c8e 100644
--- a/hugegraph-python-client/src/tests/api/test_gremlin.py
+++ b/hugegraph-python-client/src/tests/api/test_gremlin.py
@@ -50,42 +50,41 @@ class TestGremlin(unittest.TestCase):
     def test_query_all_vertices(self):
         vertices = self.gremlin.exec("g.V()")
         lst = vertices.get("data", [])
-        assert 6 == len(lst)
+        self.assertEqual(6, len(lst))
 
         self.gremlin.exec("g.V().drop()")
         vertices = self.gremlin.exec("g.V()")
         lst = vertices.get("data", [])
-        assert 0 == len(lst)
+        self.assertEqual(0, len(lst))
 
     def test_query_all_edges(self):
         edges = self.gremlin.exec("g.E()")
         lst = edges.get("data", [])
-        assert 6 == len(lst)
+        self.assertEqual(6, len(lst))
 
         self.gremlin.exec("g.E().drop()")
         edges = self.gremlin.exec("g.E()")
         lst = edges.get("data", [])
-        assert 0 == len(lst)
+        self.assertEqual(0, len(lst))
 
     def test_primitive_object(self):
         result = self.gremlin.exec("1 + 2")
-        print(result)
         result_set = result.get("data", [])
-        assert 1 == len(result_set)
+        self.assertEqual(1, len(result_set))
 
         data = result_set[0]
-        assert isinstance(data, int)
-        assert 3 == data
+        self.assertTrue(isinstance(data, int))
+        self.assertEqual(3, data)
 
     def test_empty_result_set(self):
         result = self.gremlin.exec("g.V().limit(0)")
         lst = result.get("data", [])
-        assert 0 == len(lst)
+        self.assertEqual(0, len(lst))
 
     def test_invalid_gremlin(self):
         with pytest.raises(NotFoundError):
-            assert self.gremlin.exec("g.V2()")
+            self.assertTrue(self.gremlin.exec("g.V2()"))
 
     def test_security_operation(self):
         with pytest.raises(NotFoundError):
-            assert self.gremlin.exec("System.exit(-1)")
+            self.assertTrue(self.gremlin.exec("System.exit(-1)"))
diff --git a/hugegraph-python-client/src/tests/api/test_metric.py 
b/hugegraph-python-client/src/tests/api/test_metric.py
new file mode 100644
index 0000000..ff828a3
--- /dev/null
+++ b/hugegraph-python-client/src/tests/api/test_metric.py
@@ -0,0 +1,73 @@
+# 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 unittest
+
+from tests.client_utils import ClientUtils
+
+
+class TestMetricsManager(unittest.TestCase):
+    client = None
+    metrics = None
+
+    @classmethod
+    def setUpClass(cls):
+        cls.client = ClientUtils()
+        cls.metrics = cls.client.metrics
+        cls.client.init_property_key()
+        cls.client.init_vertex_label()
+        cls.client.init_edge_label()
+        cls.client.init_index_label()
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.client.clear_graph_all_data()
+
+    def setUp(self):
+        self.client.init_vertices()
+        self.client.init_edges()
+
+    def tearDown(self):
+        pass
+
+    def test_metrics_operations(self):
+        all_basic_metrics = self.metrics.get_all_basic_metrics()
+        self.assertEqual(len(all_basic_metrics), 5)
+
+        gauges_metrics = self.metrics.get_gauges_metrics()
+        self.assertIsInstance(gauges_metrics, dict)
+
+        counters_metrics = self.metrics.get_counters_metrics()
+        self.assertIsInstance(counters_metrics, dict)
+
+        histograms_metrics = self.metrics.get_histograms_metrics()
+        self.assertIsInstance(histograms_metrics, dict)
+
+        meters_metrics = self.metrics.get_meters_metrics()
+        self.assertIsInstance(meters_metrics, dict)
+
+        timers_metrics = self.metrics.get_timers_metrics()
+        self.assertIsInstance(timers_metrics, dict)
+
+        system_metrics = self.metrics.get_system_metrics()
+        self.assertIsInstance(system_metrics, dict)
+
+        statistics = self.metrics.get_statistics_metrics()
+        self.assertIsInstance(statistics, dict)
+
+        backend_metrics = self.metrics.get_backend_metrics()
+        self.assertGreater(len(backend_metrics["hugegraph"]), 1)
diff --git a/hugegraph-python-client/src/tests/api/test_schema.py 
b/hugegraph-python-client/src/tests/api/test_schema.py
new file mode 100644
index 0000000..74b9f70
--- /dev/null
+++ b/hugegraph-python-client/src/tests/api/test_schema.py
@@ -0,0 +1,81 @@
+# 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 unittest
+
+from tests.client_utils import ClientUtils
+
+
+class TestSchemaManager(unittest.TestCase):
+    client = None
+    schema = None
+
+    @classmethod
+    def setUpClass(cls):
+        cls.client = ClientUtils()
+        cls.client.clear_graph_all_data()
+        cls.schema = cls.client.schema
+        cls.client.init_property_key()
+        cls.client.init_vertex_label()
+        cls.client.init_edge_label()
+        cls.client.init_index_label()
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.client.clear_graph_all_data()
+
+    def setUp(self):
+        pass
+
+    def tearDown(self):
+        pass
+
+    def test_get_schema(self):
+        schema = self.schema.getSchema()
+        self.assertEqual(4, len(schema))
+
+    def test_get_property_keys(self):
+        property_keys = self.schema.getPropertyKeys()
+        self.assertEqual(7, len(property_keys))
+
+    def test_get_property_key(self):
+        property_key = self.schema.getPropertyKey("name")
+        self.assertEqual(property_key.name, "name")
+
+    def test_get_vertex_labels(self):
+        vertex_labels = self.schema.getVertexLabels()
+        self.assertEqual(3, len(vertex_labels))
+
+    def test_get_vertex_label(self):
+        vertex_label = self.schema.getVertexLabel("person")
+        self.assertEqual(vertex_label.name, "person")
+
+    def test_get_edge_labels(self):
+        edge_labels = self.schema.getEdgeLabels()
+        self.assertEqual(2, len(edge_labels))
+
+    def test_get_edge_label(self):
+        edge_label = self.schema.getEdgeLabel("knows")
+        self.assertEqual(edge_label.name, "knows")
+
+    def test_get_index_labels(self):
+        index_labels = self.schema.getIndexLabels()
+        self.assertEqual(6, len(index_labels))
+
+    def test_get_index_label(self):
+        index_label = self.schema.getIndexLabel("personByCity")
+        self.assertEqual(index_label.name, "personByCity")
diff --git a/hugegraph-python-client/src/tests/api/test_task.py 
b/hugegraph-python-client/src/tests/api/test_task.py
new file mode 100644
index 0000000..9917a96
--- /dev/null
+++ b/hugegraph-python-client/src/tests/api/test_task.py
@@ -0,0 +1,64 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import unittest
+
+from pyhugegraph.utils.exceptions import NotFoundError
+from tests.client_utils import ClientUtils
+
+
+class TestTaskManager(unittest.TestCase):
+    client = None
+    task = None
+
+    @classmethod
+    def setUpClass(cls):
+        cls.client = ClientUtils()
+        cls.task = cls.client.task
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.client.clear_graph_all_data()
+
+    def setUp(self):
+        pass
+
+    def tearDown(self):
+        pass
+
+    def test_list_tasks(self):
+        tasks = self.task.list_tasks()
+        self.assertIsInstance(tasks, dict)
+        self.assertTrue("tasks" in tasks)
+
+    def test_get_task(self):
+        try:
+            self.task.get_task(1)
+        except NotFoundError as e:
+            self.assertTrue("Can\\'t find task with id \\'1\\'" in str(e))
+
+    def test_delete_task(self):
+        try:
+            self.task.delete_task(2)
+        except NotFoundError as e:
+            self.assertTrue("Can\\'t find task with id \\'2\\'" in str(e))
+
+    def test_cancel_task(self):
+        try:
+            self.task.cancel_task(3)
+        except NotFoundError as e:
+            self.assertTrue("Can\\'t find task with id \\'3\\'" in str(e))
diff --git a/hugegraph-python-client/src/tests/api/test_traverser.py 
b/hugegraph-python-client/src/tests/api/test_traverser.py
new file mode 100644
index 0000000..5c5c0c6
--- /dev/null
+++ b/hugegraph-python-client/src/tests/api/test_traverser.py
@@ -0,0 +1,259 @@
+# 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 unittest
+
+from tests.client_utils import ClientUtils
+
+
+class TestTraverserManager(unittest.TestCase):
+    client = None
+    traverser = None
+    graph = None
+
+    @classmethod
+    def setUpClass(cls):
+        cls.client = ClientUtils()
+        cls.traverser = cls.client.traverser
+        cls.graph = cls.client.graph
+        cls.client.clear_graph_all_data()
+        cls.client.init_property_key()
+        cls.client.init_vertex_label()
+        cls.client.init_edge_label()
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.client.clear_graph_all_data()
+
+    def setUp(self):
+        self.client.init_vertices()
+        self.client.init_edges()
+
+    def tearDown(self):
+        pass
+
+    def test_traverser_operations(self):
+        marko = self.graph.getVertexByCondition("person", properties={"name": 
"marko"})[0].id
+        josh = self.graph.getVertexByCondition("person", properties={"name": 
"josh"})[0].id
+        ripple = self.graph.getVertexByCondition("software", 
properties={"name": "ripple"})[0].id
+
+        k_out_result = self.traverser.k_out(marko, 2)
+        self.assertEqual(k_out_result["vertices"], ["1:peter", "2:ripple"])
+
+        k_neighbor_result = self.traverser.k_neighbor(marko, 2)
+        self.assertEqual(
+            k_neighbor_result["vertices"], ["1:peter", "1:josh", "2:lop", 
"2:ripple", "1:vadas"]
+        )
+
+        same_neighbors_result = self.traverser.same_neighbors(marko, josh)
+        self.assertEqual(same_neighbors_result["same_neighbors"], ["2:lop"])
+
+        jaccard_similarity_result = self.traverser.jaccard_similarity(marko, 
josh)
+        self.assertEqual(jaccard_similarity_result["jaccard_similarity"], 0.2)
+
+        shortest_path_result = self.traverser.shortest_path(marko, ripple, 3)
+        self.assertEqual(shortest_path_result["path"], ["1:marko", "1:josh", 
"2:ripple"])
+
+        all_shortest_paths_result = self.traverser.all_shortest_paths(marko, 
ripple, 3)
+        self.assertEqual(
+            all_shortest_paths_result["paths"], [{"objects": ["1:marko", 
"1:josh", "2:ripple"]}]
+        )
+
+        weighted_shortest_path_result = self.traverser.weighted_shortest_path(
+            marko, ripple, "weight", 3
+        )
+        self.assertEqual(
+            weighted_shortest_path_result["vertices"], ["1:marko", "1:josh", 
"2:ripple"]
+        )
+
+        single_source_shortest_path_result = 
self.traverser.single_source_shortest_path(marko, 2)
+        self.assertEqual(
+            single_source_shortest_path_result["paths"],
+            {
+                "1:peter": {"weight": 2.0, "vertices": ["1:marko", "2:lop", 
"1:peter"]},
+                "1:josh": {"weight": 1.0, "vertices": ["1:marko", "1:josh"]},
+                "2:lop": {"weight": 1.0, "vertices": ["1:marko", "2:lop"]},
+                "2:ripple": {"weight": 2.0, "vertices": ["1:marko", "1:josh", 
"2:ripple"]},
+                "1:vadas": {"weight": 1.0, "vertices": ["1:marko", "1:vadas"]},
+            },
+        )
+
+        multi_node_shortest_path_result = 
self.traverser.multi_node_shortest_path(
+            [marko, josh], max_depth=2
+        )
+        self.assertEqual(
+            multi_node_shortest_path_result["vertices"],
+            [
+                {
+                    "id": "1:marko",
+                    "label": "person",
+                    "type": "vertex",
+                    "properties": {"name": "marko", "age": 29, "city": 
"Beijing"},
+                },
+                {
+                    "id": "1:josh",
+                    "label": "person",
+                    "type": "vertex",
+                    "properties": {"name": "josh", "age": 32, "city": 
"Beijing"},
+                },
+            ],
+        )
+
+        paths_result = self.traverser.paths(marko, josh, 2)
+        self.assertEqual(
+            paths_result["paths"],
+            [{"objects": ["1:marko", "2:lop", "1:josh"]}, {"objects": 
["1:marko", "1:josh"]}],
+        )
+
+        customized_paths_result = self.traverser.customized_paths(
+            {"ids": [], "label": "person", "properties": {"name": "marko"}},
+            [
+                {
+                    "direction": "OUT",
+                    "labels": ["created"],
+                    "default_weight": 8,
+                    "max_degree": -1,
+                    "sample": 1,
+                }
+            ],
+        )
+        self.assertEqual(
+            customized_paths_result["paths"], [{"objects": ["1:marko", 
"2:lop"], "weights": [8.0]}]
+        )
+
+        sources = {"ids": [], "label": "person", "properties": {"name": 
"vadas"}}
+
+        targets = {"ids": [], "label": "software", "properties": {"name": 
"ripple"}}
+
+        steps = [
+            {
+                "direction": "IN",
+                "labels": ["knows"],
+                "properties": {},
+                "max_degree": 10000,
+                "skip_degree": 100000,
+            },
+            {
+                "direction": "OUT",
+                "labels": ["created"],
+                "properties": {},
+                "max_degree": 10000,
+                "skip_degree": 100000,
+            },
+            {
+                "direction": "IN",
+                "labels": ["created"],
+                "properties": {},
+                "max_degree": 10000,
+                "skip_degree": 100000,
+            },
+            {
+                "direction": "OUT",
+                "labels": ["created"],
+                "properties": {},
+                "max_degree": 10000,
+                "skip_degree": 100000,
+            },
+        ]
+        template_paths_result = self.traverser.template_paths(sources, 
targets, steps)
+        self.assertEqual(
+            template_paths_result["paths"],
+            [{"objects": ["1:vadas", "1:marko", "2:lop", "1:josh", 
"2:ripple"]}],
+        )
+
+        crosspoints_result = self.traverser.crosspoints(marko, josh, 2)
+        self.assertEqual(
+            crosspoints_result["crosspoints"],
+            [
+                {"crosspoint": "2:lop", "objects": ["1:marko", "2:lop", 
"1:josh"]},
+                {"crosspoint": "1:josh", "objects": ["1:marko", "1:josh"]},
+            ],
+        )
+
+        sources = {"ids": ["2:lop", "2:ripple"]}
+        path_patterns = [{"steps": [{"direction": "IN", "labels": ["created"], 
"max_degree": -1}]}]
+        customized_crosspoints_result = self.traverser.customized_crosspoints(
+            sources, path_patterns
+        )
+        self.assertEqual(customized_crosspoints_result["crosspoints"], 
["1:josh"])
+
+        rings_result = self.traverser.rings(marko, 3)
+        self.assertEqual(
+            rings_result["rings"], [{"objects": ["1:marko", "2:lop", "1:josh", 
"1:marko"]}]
+        )
+
+        rays_result = self.traverser.rays(marko, 2)
+        self.assertEqual(
+            rays_result["rays"],
+            [
+                {"objects": ["1:marko", "2:lop", "1:josh"]},
+                {"objects": ["1:marko", "2:lop", "1:peter"]},
+                {"objects": ["1:marko", "1:vadas"]},
+                {"objects": ["1:marko", "1:josh", "2:ripple"]},
+                {"objects": ["1:marko", "1:josh", "2:lop"]},
+            ],
+        )
+
+        sources = {"ids": [marko], "label": "person", "properties": {}}
+        fusiform_similarity_result = self.traverser.fusiform_similarity(
+            sources,
+            label="knows",
+            direction="OUT",
+            min_neighbors=8,
+            alpha=0.75,
+            min_similars=1,
+            top=0,
+            group_property="city",
+            min_groups=2,
+            max_degree=10000,
+            capacity=-1,
+            limit=-1,
+            with_intermediary=False,
+            with_vertex=True,
+        )
+        self.assertTrue("similars" in fusiform_similarity_result)
+
+        vertices_result = self.traverser.vertices(marko)
+        self.assertEqual(
+            vertices_result["vertices"],
+            [
+                {
+                    "id": "1:marko",
+                    "label": "person",
+                    "type": "vertex",
+                    "properties": {"name": "marko", "age": 29, "city": 
"Beijing"},
+                }
+            ],
+        )
+
+        edge_id = self.graph.getEdgeByPage("created", josh, "BOTH")[0][0]
+        edges_result = self.traverser.edges(edge_id.id)
+        self.assertEqual(
+            edges_result["edges"],
+            [
+                {
+                    "id": "S1:josh>2>>S2:lop",
+                    "label": "created",
+                    "type": "edge",
+                    "outV": "1:josh",
+                    "outVLabel": "person",
+                    "inV": "2:lop",
+                    "inVLabel": "software",
+                    "properties": {"city": "Beijing", "date": "2016-01-10 
00:00:00.000"},
+                }
+            ],
+        )
diff --git a/hugegraph-python-client/src/tests/api/test_variable.py 
b/hugegraph-python-client/src/tests/api/test_variable.py
index e50bb75..d9f2f38 100644
--- a/hugegraph-python-client/src/tests/api/test_variable.py
+++ b/hugegraph-python-client/src/tests/api/test_variable.py
@@ -43,39 +43,39 @@ class TestVariable(unittest.TestCase):
         pass
 
     def test_all(self):
-        assert 0 == len(self.variable.all())
+        self.assertEqual(len(self.variable.all()), 0)
         self.variable.set("student", "mary")
         self.variable.set("price", 20.86)
 
         dic = self.variable.all()
-        assert 2 == len(dic)
-        assert "mary" == dic.get("student", None)
-        assert 20.86 == dic.get("price", None)
+        self.assertEqual(2, len(dic))
+        self.assertEqual("mary", dic.get("student", None))
+        self.assertEqual(20.86, dic.get("price", None))
 
     def test_remove(self):
         self.variable.set("lang", "java")
         dic = self.variable.all()
-        assert 1 == len(dic)
-        assert "java" == dic.get("lang", None)
+        self.assertEqual(1, len(dic))
+        self.assertEqual("java", dic.get("lang", None))
 
         self.variable.remove("lang")
         dic = self.variable.all()
-        assert 0 == len(dic)
-        assert dic.get("lang", None) is None
+        self.assertEqual(0, len(dic))
+        self.assertEqual(dic.get("lang", None), None)
 
     def test_set_and_get(self):
         self.variable.set("name", "tom")
         self.variable.set("age", 18)
 
-        assert 2 == len(self.variable.all())
+        self.assertEqual(2, len(self.variable.all()))
         name = self.variable.get("name").get("name", None)
-        assert "tom" == name
+        self.assertEqual("tom", name)
         age = self.variable.get("age").get("age", None)
-        assert 18 == age
+        self.assertEqual(18, age)
 
     def test_get_key_not_exist(self):
         with pytest.raises(NotFoundError):
-            assert self.variable.get("id").get("id") is None
+            self.assertIsNone(self.variable.get("id").get("id"))
 
     def test_remove_key_not_exist(self):
         self.variable.remove("id")
diff --git a/hugegraph-python-client/src/tests/client_utils.py 
b/hugegraph-python-client/src/tests/client_utils.py
index 9eacccb..cc3c108 100644
--- a/hugegraph-python-client/src/tests/client_utils.py
+++ b/hugegraph-python-client/src/tests/client_utils.py
@@ -37,6 +37,10 @@ class ClientUtils:
         self.graph = self.client.graph()
         self.graphs = self.client.graphs()
         self.variable = self.client.variable()
+        self.auth = self.client.auth()
+        self.task = self.client.task()
+        self.metrics = self.client.metrics()
+        self.traverser = self.client.traverser()
 
     def init_property_key(self):
         schema = self.schema
@@ -71,6 +75,21 @@ class ClientUtils:
             "date", "city"
         ).nullableKeys("city").ifNotExist().create()
 
+    def init_index_label(self):
+        schema = self.schema
+        
schema.indexLabel("personByCity").onV("person").by("city").secondary().ifNotExist().create()
+        
schema.indexLabel("personByAge").onV("person").by("age").range().ifNotExist().create()
+        schema.indexLabel("softwareByPrice").onV("software").by(
+            "price"
+        ).range().ifNotExist().create()
+        schema.indexLabel("softwareByLang").onV("software").by(
+            "lang"
+        ).secondary().ifNotExist().create()
+        
schema.indexLabel("knowsByDate").onE("knows").by("date").secondary().ifNotExist().create()
+        schema.indexLabel("createdByDate").onE("created").by(
+            "date"
+        ).secondary().ifNotExist().create()
+
     def init_vertices(self):
         graph = self.graph
         graph.addVertex("person", {"name": "marko", "age": 29, "city": 
"Beijing"})
diff --git a/style/code_format_and_analysis.sh 
b/style/code_format_and_analysis.sh
index 225e751..8321e53 100644
--- a/style/code_format_and_analysis.sh
+++ b/style/code_format_and_analysis.sh
@@ -38,5 +38,5 @@ if [ "$PYLINT" = true ] ; then
   we need to manually fix all the warnings mentioned below before commit! "
   export 
PYTHONPATH=${ROOT_DIR}/hugegraph-llm/src:${ROOT_DIR}/hugegraph-python-client/src
   pylint --rcfile=${ROOT_DIR}/style/pylint.conf ${ROOT_DIR}/hugegraph-llm
-  #pylint --rcfile=${ROOT_DIR}/style/pylint.conf 
${ROOT_DIR}/hugegraph-python-client
+  pylint --rcfile=${ROOT_DIR}/style/pylint.conf --disable C0103 
${ROOT_DIR}/hugegraph-python-client
 fi
diff --git a/style/pylint.conf b/style/pylint.conf
index a3638df..2ae3281 100644
--- a/style/pylint.conf
+++ b/style/pylint.conf
@@ -443,8 +443,12 @@ disable=raw-checker-failed,
         R0801,  # Similar lines
         W0105,  # String statement has no effect (pointless-string-statement)
         R0913,  # Too many arguments (6/5) (too-many-arguments)
-        C0415,   # Import outside toplevel
-        R0902   # Too many instance attributes (11/7)
+        C0415,  # Import outside toplevel
+        R0902,  # Too many instance attributes (11/7)
+        R1725,  # Consider using Python 3 style super() without arguments 
(super-with-arguments)
+        W0622,  # Redefining built-in 'id' (redefined-builtin)
+        R0904   # Too many public methods (27/20) (too-many-public-methods)
+
 # Enable the message, report, category or checker with the given id(s). You can
 # either give multiple identifier separated by comma (,) or put this option
 # multiple time (only on the command line, not in the configuration file where

Reply via email to