def functions(self): """List the AQL functions defined in this database. :returns: a mapping of AQL function names to its javascript code :rtype: dict :raises arango.exceptions.AQLFunctionListError: if the AQL functions cannot be retrieved """ request = Request(method='get', endpoint='/_api/aqlfunction') def handler(res): if res.status_code not in HTTP_OK: raise AQLFunctionListError(res) body = res.body or {} return {func['name']: func['code'] for func in map(dict, body)} return request, handler
def configure(self, sync=None, journal_size=None): """Configure the collection properties. Only *sync* and *journal_size* properties are configurable. :param sync: wait for the operation to sync to disk :type sync: bool :param journal_size: the journal size :type journal_size: int :returns: the new collection properties :rtype: dict :raises arango.exceptions.CollectionConfigureError: if the collection properties cannot be configured """ data = {} if sync is not None: data['waitForSync'] = sync if journal_size is not None: data['journalSize'] = journal_size request = Request(method='put', endpoint='/_api/collection/{}/properties'.format( self._name), data=data) def handler(res): if res.status_code not in HTTP_OK: raise CollectionConfigureError(res) result = { 'id': res.body['id'], 'name': res.body['name'], 'edge': res.body['type'] == 3, 'sync': res.body['waitForSync'], 'status': self._status(res.body['status']), 'compact': res.body['doCompact'], 'system': res.body['isSystem'], 'volatile': res.body['isVolatile'], 'journal_size': res.body['journalSize'], 'keygen': res.body['keyOptions']['type'], 'user_keys': res.body['keyOptions']['allowUserKeys'], 'key_increment': res.body['keyOptions'].get('increment'), 'key_offset': res.body['keyOptions'].get('offset') } return result return request, handler
def server_role(self) -> Result[str]: """Return the server role. :return: Server role. Possible values are "SINGLE" (server which is not in a cluster), "COORDINATOR" (cluster coordinator), "PRIMARY", "SECONDARY", "AGENT" (Agency server in a cluster) or "UNDEFINED". :rtype: str :raise arango.exceptions.ClusterServerRoleError: If retrieval fails. """ request = Request(method="get", endpoint="/_admin/server/role") def response_handler(resp: Response) -> str: if resp.is_success: return str(resp.body["role"]) raise ClusterServerRoleError(resp, request) return self._execute(request, response_handler)
def kill(self, query_id: str) -> Result[bool]: """Kill a running query. :param query_id: Query ID. :type query_id: str :return: True if kill request was sent successfully. :rtype: bool :raise arango.exceptions.AQLQueryKillError: If the send fails. """ request = Request(method="delete", endpoint=f"/_api/query/{query_id}") def response_handler(resp: Response) -> bool: if not resp.is_success: raise AQLQueryKillError(resp, request) return True return self._execute(request, response_handler)
def server_role(self): """Return the server role. :return: Server role. Possible values are "SINGLE" (server which is not in a cluster), "COORDINATOR" (cluster coordinator), "PRIMARY", "SECONDARY", "AGENT" (Agency node in a cluster) or "UNDEFINED". :rtype: str | unicode :raise arango.exceptions.ClusterServerRoleError: If retrieval fails. """ request = Request(method='get', endpoint='/_admin/server/role') def response_handler(resp): if resp.is_success: return resp.body['role'] raise ClusterServerRoleError(resp, request) return self._execute(request, response_handler)
def properties(self): """Return the properties of the query cache. :returns: the cache properties :rtype: dict :raises arango.exceptions.AQLCachePropertiesError: if the cache properties cannot be retrieved """ request = Request(method='get', endpoint='/_api/query-cache/properties') def handler(res): if res.status_code not in HTTP_OK: raise AQLCachePropertiesError(res) return {'mode': res.body['mode'], 'limit': res.body['maxResults']} return request, handler
def ping(self): """Ping the next host to check if connection is established. :return: Response status code. :rtype: int """ request = Request( method='get', endpoint='/_api/collection' ) resp = self.send_request(request) if resp.status_code in {401, 403}: raise ServerConnectionError('bad username and/or password') if not resp.is_success: # pragma: no cover raise ServerConnectionError( resp.error_message or 'bad server response') return resp.status_code
def fetch(self): """Fetch the next batch from server and update the cursor. :return: New batch details. :rtype: dict :raise arango.exceptions.CursorNextError: If batch retrieval fails. :raise arango.exceptions.CursorStateError: If cursor ID is not set. """ if self._id is None: raise CursorStateError('cursor ID not set') request = Request(method='put', endpoint='/_api/{}/{}'.format(self._type, self._id)) resp = self._conn.send_request(request) if not resp.is_success: raise CursorNextError(resp, request) return self._update(resp.body)
def server_count(self) -> Result[int]: """Return the number of servers in the cluster. :return: Number of servers in the cluster. :rtype: int :raise arango.exceptions.ClusterServerCountError: If retrieval fails. """ request = Request(method="get", endpoint="/_admin/cluster/numberOfServers") def response_handler(resp: Response) -> int: if resp.is_success: result: int = resp.body return result raise ClusterServerCountError(resp, request) return self._execute(request, response_handler)
def create_service_with_file(self, mount, filename, development=None, setup=None, legacy=None): """Install a new service using a javascript file or zip bundle. :param mount: Service mount path (e.g "/_admin/aardvark"). :type mount: str | unicode :param filename: Full path to the javascript file or zip bundle. :type filename: str | unicode :param development: Enable development mode. :type development: bool :param setup: Run service setup script. :type setup: bool :param legacy: Install the service in 2.8 legacy compatibility mode. :type legacy: bool :return: Service metadata. :rtype: dict :raise arango.exceptions.FoxxServiceCreateError: If install fails. """ params = {'mount': mount} if development is not None: params['development'] = development if setup is not None: params['setup'] = setup if legacy is not None: params['legacy'] = legacy data = self._encode_file(filename) request = Request( method='post', endpoint='/_api/foxx', params=params, data=data, headers={'content-type': data.content_type} ) def response_handler(resp): if not resp.is_success: raise FoxxServiceCreateError(resp, request) return resp.body return self._execute(request, response_handler)
def replace(self, document, sync=None): """Replace a document by its key in the edge collection. The ``"_key"``, ``"_from"`` and ``"_to"`` fields must be present in **document**. If the ``"_rev"`` field is present in **document**, its value is compared against the revision of the target document. :param document: the new document :type document: dict :param sync: wait for the operation to sync to disk :type sync: bool | None :returns: the ID, revision and key of the replaced document :rtype: dict :raises arango.exceptions.DocumentRevisionError: if the given revision does not match the revision of the target document :raises arango.exceptions.DocumentReplaceError: if the document cannot be replaced """ headers, params = {}, {} if sync is not None: params['waitForSync'] = sync revision = document.get('_rev') if revision is not None: headers['If-Match'] = revision request = Request( method='put', endpoint='/_api/gharial/{}/edge/{}/{}'.format( self._graph_name, self._name, document['_key'] ), data=document, params=params, headers=headers ) def handler(res): if res.status_code == 412: raise DocumentRevisionError(res) elif res.status_code not in HTTP_OK: raise DocumentReplaceError(res) edge = res.body["edge"] edge['_old_rev'] = edge.pop('_oldRev') return edge return request, handler
def create_edge_definition( self, edge_collection: str, from_vertex_collections: Sequence[str], to_vertex_collections: Sequence[str], ) -> Result[EdgeCollection]: """Create a new edge definition. An edge definition consists of an edge collection, "from" vertex collection(s) and "to" vertex collection(s). Here is an example entry: .. code-block:: python { 'edge_collection': 'edge_collection_name', 'from_vertex_collections': ['from_vertex_collection_name'], 'to_vertex_collections': ['to_vertex_collection_name'] } :param edge_collection: Edge collection name. :type edge_collection: str :param from_vertex_collections: Names of "from" vertex collections. :type from_vertex_collections: [str] :param to_vertex_collections: Names of "to" vertex collections. :type to_vertex_collections: [str] :return: Edge collection API wrapper. :rtype: arango.collection.EdgeCollection :raise arango.exceptions.EdgeDefinitionCreateError: If create fails. """ request = Request( method="post", endpoint=f"/_api/gharial/{self._name}/edge", data={ "collection": edge_collection, "from": from_vertex_collections, "to": to_vertex_collections, }, ) def response_handler(resp: Response) -> EdgeCollection: if resp.is_success: return self.edge_collection(edge_collection) raise EdgeDefinitionCreateError(resp, request) return self._execute(request, response_handler)
def refresh_token(self) -> None: """Get a new JWT token for the current user (cannot be a superuser). :return: JWT token. :rtype: str """ request = Request( method="post", endpoint="/_open/auth", data={ "username": self._username, "password": self._password }, ) host_index = self._host_resolver.get_host_index() resp = self._http.send_request( session=self._sessions[host_index], method=request.method, url=self._url_prefixes[host_index] + request.endpoint, data=self.normalize_data(request.data), ) resp = self.prep_response(resp) if not resp.is_success: raise JWTAuthError(resp, request) self._token = resp.body["jwt"] assert self._token is not None jwt_payload = jwt.decode( self._token, issuer="arangodb", algorithms=["HS256"], options={ "require_exp": True, "require_iat": True, "verify_iat": True, "verify_exp": True, "verify_signature": False, }, ) self._token_exp = jwt_payload["exp"] self._auth_header = f"bearer {self._token}"
def clear_slow_queries(self): """Clear slow AQL queries. :return: True if slow queries were cleared successfully. :rtype: bool :raise arango.exceptions.AQLQueryClearError: If operation fails. """ request = Request( method='delete', endpoint='/_api/query/slow' ) def response_handler(resp): if not resp.is_success: raise AQLQueryClearError(resp, request) return True return self._execute(request, response_handler)
def vertex_collections(self) -> Result[List[str]]: """Return vertex collections in the graph that are not orphaned. :return: Names of vertex collections that are not orphaned. :rtype: [str] :raise arango.exceptions.VertexCollectionListError: If retrieval fails. """ request = Request( method="get", endpoint=f"/_api/gharial/{self._name}/vertex", ) def response_handler(resp: Response) -> List[str]: if not resp.is_success: raise VertexCollectionListError(resp, request) return sorted(set(resp.body["collections"])) return self._execute(request, response_handler)
def server_id(self) -> Result[str]: """Return this server's ID. :return: Server ID. :rtype: str :raise arango.exceptions.ReplicationServerIDError: If retrieval fails. """ request = Request( method="get", endpoint="/_api/replication/server-id", ) def response_handler(resp: Response) -> str: if resp.is_success: return str(resp.body["serverId"]) raise ReplicationServerIDError(resp, request) return self._execute(request, response_handler)
def stop_applier(self) -> Result[Json]: """Stop the replication applier. :return: Applier state and details. :rtype: dict :raise arango.exceptions.ReplicationApplierStopError: If operation fails. """ request = Request( method="put", endpoint="/_api/replication/applier-stop", ) def response_handler(resp: Response) -> Json: if resp.is_success: return format_replication_applier_state(resp.body) raise ReplicationApplierStopError(resp, request) return self._execute(request, response_handler)
def applier_state(self) -> Result[Json]: """Return the state of the replication applier :return: Applier state and details. :rtype: dict :raise arango.exceptions.ReplicationApplierStateError: If retrieval fails. """ request = Request( method="get", endpoint="/_api/replication/applier-state", ) def response_handler(resp: Response) -> Json: if resp.is_success: return format_replication_applier_state(resp.body) raise ReplicationApplierStateError(resp, request) return self._execute(request, response_handler)
def logger_first_tick(self) -> Result[str]: """Return the first available tick value from the server. :return: First tick value. :rtype: str :raise arango.exceptions.ReplicationLoggerFirstTickError: If retrieval fails. """ request = Request( method="get", endpoint="/_api/replication/logger-first-tick", ) def response_handler(resp: Response) -> str: if resp.is_success: return str(resp.body["firstTick"]) raise ReplicationLoggerFirstTickError(resp, request) return self._execute(request, response_handler)
def vertex_collections(self): """Return the vertex collections of the graph. :returns: the names of the vertex collections :rtype: list :raises arango.exceptions.VertexCollectionListError: if the list of vertex collections cannot be retrieved """ request = Request(method='get', endpoint='/_api/gharial/{}/vertex'.format( self._name)) def handler(res): if res.status_code not in HTTP_OK: raise VertexCollectionListError(res) return res.body['collections'] return request, handler
def clear(self): """Clear the query cache. :return: True if query cache was cleared successfully. :rtype: bool :raise arango.exceptions.AQLCacheClearError: If operation fails. """ request = Request( method='delete', endpoint='/_api/query-cache' ) def response_handler(resp): if not resp.is_success: raise AQLCacheClearError(resp, request) return True return self._execute(request, response_handler)
def entries(self): """Return the query cache entries. :return: Query cache entries. :rtype: list :raise AQLCacheEntriesError: If retrieval fails. """ request = Request( method='get', endpoint='/_api/query-cache/entries' ) def response_handler(resp): if not resp.is_success: raise AQLCacheEntriesError(resp, request) return resp.body return self._execute(request, response_handler)
def random(self): """Return a random document from the collection. :returns: a random document :rtype: dict :raises arango.exceptions.DocumentGetError: if the document cannot be fetched from the collection """ request = Request(method='put', endpoint='/_api/simple/any', data={'collection': self._name}) def handler(res): if res.status_code not in HTTP_OK: raise DocumentGetError(res) return res.body['document'] return request, handler
def server_id(self): """Return this server's ID. :return: Server ID. :rtype: str :raise arango.exceptions.ReplicationServerIDError: If retrieval fails. """ request = Request( method='get', endpoint='/_api/replication/server-id', ) def response_handler(resp): if resp.is_success: return resp.body['serverId'] raise ReplicationServerIDError(resp, request) return self._execute(request, response_handler)
def delete_job(self, job_id): """Delete a Pregel job. :param job_id: Pregel job ID. :type job_id: int :return: True if Pregel job was deleted successfully. :rtype: bool :raise arango.exceptions.PregelJobDeleteError: If delete fails. """ request = Request(method='delete', endpoint='/_api/control_pregel/{}'.format(job_id)) def response_handler(resp): if resp.is_success: return True raise PregelJobDeleteError(resp, request) return self._execute(request, response_handler)
def slow_queries(self): """Return a list of all slow AQL queries. :return: Slow AQL queries. :rtype: [dict] :raise arango.exceptions.AQLQueryListError: If retrieval fails. """ request = Request( method='get', endpoint='/_api/query/slow' ) def response_handler(resp): if not resp.is_success: raise AQLQueryListError(resp, request) return [format_aql_query(q) for q in resp.body] return self._execute(request, response_handler)
def kill(self, query_id): """Kill a running query. :param query_id: Query ID. :type query_id: str | unicode :return: True if kill request was sent successfully. :rtype: bool :raise arango.exceptions.AQLQueryKillError: If the send fails. """ request = Request(method='delete', endpoint='/_api/query/{}'.format(query_id)) def response_handler(resp): if not resp.is_success: raise AQLQueryKillError(resp, request) return True return self._execute(request, response_handler)
def tracking(self): """Return AQL query tracking properties. :return: AQL query tracking properties. :rtype: dict :raise arango.exceptions.AQLQueryTrackingGetError: If retrieval fails. """ request = Request( method='get', endpoint='/_api/query/properties' ) def response_handler(resp): if not resp.is_success: raise AQLQueryTrackingGetError(resp, request) return format_aql_tracking(resp.body) return self._execute(request, response_handler)
def vertex_collections(self): """Return vertex collections in the graph that are not orphaned. :return: Names of vertex collections that are not orphaned. :rtype: [str | unicode] :raise arango.exceptions.VertexCollectionListError: If retrieval fails. """ request = Request( method='get', endpoint='/_api/gharial/{}/vertex'.format(self._name), ) def response_handler(resp): if not resp.is_success: raise VertexCollectionListError(resp, request) return sorted(set(resp.body['collections'])) return self._execute(request, response_handler)
def properties(self): """Return the query cache properties. :return: Query cache properties. :rtype: dict :raise arango.exceptions.AQLCachePropertiesError: If retrieval fails. """ request = Request( method='get', endpoint='/_api/query-cache/properties' ) def response_handler(resp): if not resp.is_success: raise AQLCachePropertiesError(resp, request) return format_aql_cache(resp.body) return self._execute(request, response_handler)