diff --git a/astrapy/db.py b/astrapy/db.py index 274af424..792b107c 100644 --- a/astrapy/db.py +++ b/astrapy/db.py @@ -35,6 +35,15 @@ def __init__( api_endpoint=None, namespace=None, ): + """ + Initialize an AstraDBCollection instance. + Args: + collection_name (str): The name of the collection. + astra_db (AstraDB, optional): An instance of Astra DB. + token (str, optional): Authentication token for Astra DB. + api_endpoint (str, optional): API endpoint URL. + namespace (str, optional): Namespace for the database. + """ if astra_db is None: if token is None or api_endpoint is None: raise AssertionError("Must provide token and api_endpoint") @@ -47,6 +56,9 @@ def __init__( self.collection_name = collection_name self.base_path = f"{self.astra_db.base_path}/{self.collection_name}" + def __repr__(self): + return f'Astra DB Collection[name="{self.collection_name}", endpoint="{self.astra_db.base_url}"]' + def _request(self, *args, skip_error_check=False, **kwargs): response = make_request( *args, @@ -131,9 +143,26 @@ def _post_process_find( return final_result def get(self, path=None): + """ + Retrieve a document from the collection by its path. + Args: + path (str, optional): The path of the document to retrieve. + Returns: + dict: The retrieved document. + """ return self._get(path=path) def find(self, filter=None, projection=None, sort={}, options=None): + """ + Find documents in the collection that match the given filter. + Args: + filter (dict, optional): Criteria to filter documents. + projection (dict, optional): Specifies the fields to return. + sort (dict, optional): Specifies the order in which to return matching documents. + options (dict, optional): Additional options for the query. + Returns: + dict: The query response containing matched documents. + """ json_query = make_payload( top_level="find", filter=filter, @@ -157,6 +186,17 @@ def vector_find( fields=None, include_similarity=True, ): + """ + Perform a vector-based search in the collection. + Args: + vector (list): The vector to search with. + limit (int): The maximum number of documents to return. + filter (dict, optional): Criteria to filter documents. + fields (list, optional): Specifies the fields to return. + include_similarity (bool, optional): Whether to include similarity score in the result. + Returns: + list: A list of documents matching the vector search criteria. + """ # Must pass a limit if not limit: return ValueError("Must pass a limit") @@ -188,6 +228,15 @@ def vector_find( @staticmethod def paginate(*, method, options, **kwargs): + """ + Generate paginated results for a given database query method. + Args: + method (function): The database query method to paginate. + options (dict): Options for the database query. + kwargs: Additional arguments to pass to the database query method. + Yields: + dict: The next document in the paginated result set. + """ response0 = method(options=options, **kwargs) next_page_state = response0["data"]["nextPageState"] options0 = options @@ -201,6 +250,16 @@ def paginate(*, method, options, **kwargs): next_page_state = response1["data"]["nextPageState"] def paginated_find(self, filter=None, projection=None, sort=None, options=None): + """ + Perform a paginated search in the collection. + Args: + filter (dict, optional): Criteria to filter documents. + projection (dict, optional): Specifies the fields to return. + sort (dict, optional): Specifies the order in which to return matching documents. + options (dict, optional): Additional options for the query. + Returns: + generator: A generator yielding documents in the paginated result set. + """ return self.paginate( method=self.find, filter=filter, @@ -210,6 +269,15 @@ def paginated_find(self, filter=None, projection=None, sort=None, options=None): ) def pop(self, filter, update, options): + """ + Update a document in the collection and return the original document. + Args: + filter (dict): Criteria to identify the document to update. + update (dict): The update to apply to the document. + options (dict): Additional options for the update operation. + Returns: + dict: The original document before the update. + """ json_query = make_payload( top_level="findOneAndUpdate", filter=filter, update=update, options=options ) @@ -223,6 +291,15 @@ def pop(self, filter, update, options): return response def push(self, filter, update, options): + """ + Add an item to an array field of a document in the collection. + Args: + filter (dict): Criteria to identify the document to update. + update (dict): The update to apply to the document. + options (dict): Additional options for the update operation. + Returns: + dict: The result of the update operation. + """ json_query = make_payload( top_level="findOneAndUpdate", filter=filter, update=update, options=options ) @@ -238,6 +315,16 @@ def push(self, filter, update, options): def find_one_and_replace( self, sort={}, filter=None, replacement=None, options=None ): + """ + Find a single document and replace it. + Args: + sort (dict, optional): Specifies the order in which to find the document. + filter (dict, optional): Criteria to filter documents. + replacement (dict): The new document to replace the existing one. + options (dict, optional): Additional options for the operation. + Returns: + dict: The result of the find and replace operation. + """ json_query = make_payload( top_level="findOneAndReplace", filter=filter, @@ -260,6 +347,16 @@ def vector_find_one_and_replace( filter=None, fields=None, ): + """ + Perform a vector-based search and replace the first matched document. + Args: + vector (dict): The vector to search with. + replacement (dict): The new document to replace the existing one. + filter (dict, optional): Criteria to filter documents. + fields (list, optional): Specifies the fields to return in the result. + Returns: + dict: The result of the vector find and replace operation. + """ # Pre-process the included arguments sort, _ = self._pre_process_find( vector, @@ -283,6 +380,16 @@ def vector_find_one_and_replace( return find_result def find_one_and_update(self, sort={}, update=None, filter=None, options=None): + """ + Find a single document and update it. + Args: + sort (dict, optional): Specifies the order in which to find the document. + update (dict, optional): The update to apply to the document. + filter (dict, optional): Criteria to filter documents. + options (dict, optional): Additional options for the operation. + Returns: + dict: The result of the find and update operation. + """ json_query = make_payload( top_level="findOneAndUpdate", filter=filter, @@ -307,6 +414,16 @@ def vector_find_one_and_update( filter=None, fields=None, ): + """ + Perform a vector-based search and update the first matched document. + Args: + vector (list): The vector to search with. + update (dict): The update to apply to the matched document. + filter (dict, optional): Criteria to filter documents before applying the vector search. + fields (list, optional): Specifies the fields to return in the updated document. + Returns: + dict: The result of the vector-based find and update operation. + """ # Pre-process the included arguments sort, _ = self._pre_process_find( vector, @@ -330,6 +447,16 @@ def vector_find_one_and_update( return find_result def find_one(self, filter={}, projection={}, sort={}, options={}): + """ + Find a single document in the collection. + Args: + filter (dict, optional): Criteria to filter documents. + projection (dict, optional): Specifies the fields to return. + sort (dict, optional): Specifies the order in which to return the document. + options (dict, optional): Additional options for the query. + Returns: + dict: The found document or None if no matching document is found. + """ json_query = make_payload( top_level="findOne", filter=filter, @@ -352,6 +479,16 @@ def vector_find_one( fields=None, include_similarity=True, ): + """ + Perform a vector-based search to find a single document in the collection. + Args: + vector (list): The vector to search with. + filter (dict, optional): Additional criteria to filter documents. + fields (list, optional): Specifies the fields to return in the result. + include_similarity (bool, optional): Whether to include similarity score in the result. + Returns: + dict: The found document or None if no matching document is found. + """ # Pre-process the included arguments sort, projection = self._pre_process_find( vector, @@ -376,6 +513,13 @@ def vector_find_one( return find_result def insert_one(self, document): + """ + Insert a single document into the collection. + Args: + document (dict): The document to insert. + Returns: + dict: The response from the database after the insert operation. + """ json_query = make_payload(top_level="insertOne", document=document) response = self._request( @@ -385,6 +529,15 @@ def insert_one(self, document): return response def insert_many(self, documents, options=None, partial_failures_allowed=False): + """ + Insert multiple documents into the collection. + Args: + documents (list): A list of documents to insert. + options (dict, optional): Additional options for the insert operation. + partial_failures_allowed (bool, optional): Whether to allow partial failures in the batch. + Returns: + dict: The response from the database after the insert operation. + """ json_query = make_payload( top_level="insertMany", documents=documents, options=options ) @@ -399,6 +552,14 @@ def insert_many(self, documents, options=None, partial_failures_allowed=False): return response def update_one(self, filter, update): + """ + Update a single document in the collection. + Args: + filter (dict): Criteria to identify the document to update. + update (dict): The update to apply to the document. + Returns: + dict: The response from the database after the update operation. + """ json_query = make_payload(top_level="updateOne", filter=filter, update=update) response = self._request( @@ -410,9 +571,24 @@ def update_one(self, filter, update): return response def replace(self, path, document): + """ + Replace a document in the collection. + Args: + path (str): The path to the document to replace. + document (dict): The new document to replace the existing one. + Returns: + dict: The response from the database after the replace operation. + """ return self._put(path=path, document=document) def delete(self, id): + """ + Delete a single document from the collection based on its ID. + Args: + id (str): The ID of the document to delete. + Returns: + dict: The response from the database after the delete operation. + """ json_query = { "deleteOne": { "filter": {"_id": id}, @@ -426,6 +602,14 @@ def delete(self, id): return response def delete_subdocument(self, id, subdoc): + """ + Delete a subdocument or field from a document in the collection. + Args: + id (str): The ID of the document containing the subdocument. + subdoc (str): The key of the subdocument or field to remove. + Returns: + dict: The response from the database after the update operation. + """ json_query = { "findOneAndUpdate": { "filter": {"_id": id}, @@ -441,10 +625,14 @@ def delete_subdocument(self, id, subdoc): def upsert(self, document): """ - Emulate an upsert operation for a single document, - whereby a document is inserted if its _id is new, or completely - replaces and existing one if that _id is already saved in the collection. - Returns: the _id of the inserted document. + Emulate an upsert operation for a single document in the collection. + This method attempts to insert the document. If a document with the same _id exists, it updates the existing document. + + Args: + document (dict): The document to insert or update. + + Returns: + str: The _id of the inserted or updated document. """ # Attempt to insert the given document result = self.insert_one(document) @@ -476,6 +664,13 @@ def __init__( api_version=None, namespace=None, ): + """ + Initialize an Astra DB instance. + Args: + token (str, optional): Authentication token for Astra DB. + api_endpoint (str, optional): API endpoint URL. + namespace (str, optional): Namespace for the database. + """ if token is None or api_endpoint is None: raise AssertionError("Must provide token and api_endpoint") @@ -501,6 +696,9 @@ def __init__( # Finally, construct the full base path self.base_path = f"/{self.api_path}/{self.api_version}/{self.namespace}" + def __repr__(self): + return f'Astra DB[endpoint="{self.base_url}"]' + def _request(self, *args, skip_error_check=False, **kwargs): response = make_request( *args, @@ -518,9 +716,21 @@ def _request(self, *args, skip_error_check=False, **kwargs): return responsebody def collection(self, collection_name): + """ + Retrieve a collection from the database. + Args: + collection_name (str): The name of the collection to retrieve. + Returns: + AstraDBCollection: The collection object. + """ return AstraDBCollection(collection_name=collection_name, astra_db=self) def get_collections(self): + """ + Retrieve a list of collections from the database. + Returns: + dict: A list of collections in the database. + """ response = self._request( method=http_methods.POST, path=self.base_path, @@ -532,6 +742,16 @@ def get_collections(self): def create_collection( self, collection_name, *, options=None, dimension=None, metric="" ): + """ + Create a new collection in the database. + Args: + collection_name (str): The name of the collection to create. + options (dict, optional): Options for the collection. + dimension (int, optional): Dimension for vector search. + metric (str, optional): Metric type for vector search. + Returns: + AstraDBCollection: The created collection object. + """ # Make sure we provide a collection name if not collection_name: raise ValueError("Must provide a collection name") @@ -574,6 +794,13 @@ def create_collection( return AstraDBCollection(astra_db=self, collection_name=collection_name) def delete_collection(self, collection_name): + """ + Delete a collection from the database. + Args: + collection_name (str): The name of the collection to delete. + Returns: + dict: The response from the database. + """ # Make sure we provide a collection name if not collection_name: raise ValueError("Must provide a collection name") diff --git a/astrapy/ops.py b/astrapy/ops.py index c8579323..cc1bcd36 100644 --- a/astrapy/ops.py +++ b/astrapy/ops.py @@ -44,6 +44,15 @@ def _ops_request(self, method, path, options=None, json_data=None): ) def get_databases(self, options=None): + """ + Retrieve a list of databases. + + Args: + options (dict, optional): Additional options for the request. + + Returns: + dict: A JSON response containing the list of databases. + """ response = self._ops_request( method=http_methods.GET, path="/databases", options=options ).json() @@ -51,6 +60,15 @@ def get_databases(self, options=None): return response def create_database(self, database_definition=None): + """ + Create a new database. + + Args: + database_definition (dict, optional): A dictionary defining the properties of the database to be created. + + Returns: + dict: A dictionary containing the ID of the created database, or None if creation was unsuccessful. + """ r = self._ops_request( method=http_methods.POST, path="/databases", json_data=database_definition ) @@ -61,6 +79,15 @@ def create_database(self, database_definition=None): return None def terminate_database(self, database=""): + """ + Terminate an existing database. + + Args: + database (str): The identifier of the database to terminate. + + Returns: + str: The identifier of the terminated database, or None if termination was unsuccessful. + """ r = self._ops_request( method=http_methods.POST, path=f"/databases/{database}/terminate" ) @@ -71,6 +98,16 @@ def terminate_database(self, database=""): return None def get_database(self, database="", options=None): + """ + Retrieve details of a specific database. + + Args: + database (str): The identifier of the database to retrieve. + options (dict, optional): Additional options for the request. + + Returns: + dict: A JSON response containing the details of the specified database. + """ return self._ops_request( method=http_methods.GET, path=f"/databases/{database}", @@ -78,22 +115,60 @@ def get_database(self, database="", options=None): ).json() def create_keyspace(self, database="", keyspace=""): + """ + Create a keyspace in a specified database. + + Args: + database (str): The identifier of the database where the keyspace will be created. + keyspace (str): The name of the keyspace to create. + + Returns: + requests.Response: The response object from the HTTP request. + """ return self._ops_request( method=http_methods.POST, path=f"/databases/{database}/keyspaces/{keyspace}", ) def park_database(self, database=""): + """ + Park a specific database, making it inactive. + + Args: + database (str): The identifier of the database to park. + + Returns: + dict: The response from the server after parking the database. + """ return self._ops_request( method=http_methods.POST, path=f"/databases/{database}/park" ).json() def unpark_database(self, database=""): + """ + Unpark a specific database, making it active again. + + Args: + database (str): The identifier of the database to unpark. + + Returns: + dict: The response from the server after unparking the database. + """ return self._ops_request( method=http_methods.POST, path=f"/databases/{database}/unpark" ).json() def resize_database(self, database="", options=None): + """ + Resize a specific database according to provided options. + + Args: + database (str): The identifier of the database to resize. + options (dict, optional): The specifications for the resize operation. + + Returns: + dict: The response from the server after the resize operation. + """ return self._ops_request( method=http_methods.POST, path=f"/databases/{database}/resize", @@ -101,6 +176,16 @@ def resize_database(self, database="", options=None): ).json() def reset_database_password(self, database="", options=None): + """ + Reset the password for a specific database. + + Args: + database (str): The identifier of the database for which to reset the password. + options (dict, optional): Additional options for the password reset. + + Returns: + dict: The response from the server after resetting the password. + """ return self._ops_request( method=http_methods.POST, path=f"/databases/{database}/resetPassword", @@ -108,18 +193,46 @@ def reset_database_password(self, database="", options=None): ).json() def get_secure_bundle(self, database=""): + """ + Retrieve a secure bundle URL for a specific database. + + Args: + database (str): The identifier of the database for which to get the secure bundle. + + Returns: + dict: The secure bundle URL and related information. + """ return self._ops_request( method=http_methods.POST, path=f"/databases/{database}/secureBundleURL", ).json() def get_datacenters(self, database=""): + """ + Get a list of datacenters associated with a specific database. + + Args: + database (str): The identifier of the database for which to list datacenters. + + Returns: + dict: A list of datacenters and their details. + """ return self._ops_request( method=http_methods.GET, path=f"/databases/{database}/datacenters", ).json() def create_datacenter(self, database="", options=None): + """ + Create a new datacenter for a specific database. + + Args: + database (str): The identifier of the database for which to create the datacenter. + options (dict, optional): Specifications for the new datacenter. + + Returns: + dict: The response from the server after creating the datacenter. + """ return self._ops_request( method=http_methods.POST, path=f"/databases/{database}/datacenters", @@ -127,18 +240,47 @@ def create_datacenter(self, database="", options=None): ).json() def terminate_datacenter(self, database="", datacenter=""): + """ + Terminate a specific datacenter in a database. + + Args: + database (str): The identifier of the database containing the datacenter. + datacenter (str): The identifier of the datacenter to terminate. + + Returns: + dict: The response from the server after terminating the datacenter. + """ return self._ops_request( method=http_methods.POST, path=f"/databases/{database}/datacenters/{datacenter}/terminate", ).json() def get_access_list(self, database=""): + """ + Retrieve the access list for a specific database. + + Args: + database (str): The identifier of the database for which to get the access list. + + Returns: + dict: The current access list for the database. + """ return self._ops_request( method=http_methods.GET, path=f"/databases/{database}/access-list", ).json() def replace_access_list(self, database="", access_list=None): + """ + Replace the entire access list for a specific database. + + Args: + database (str): The identifier of the database for which to replace the access list. + access_list (dict): The new access list to be set. + + Returns: + dict: The response from the server after replacing the access list. + """ return self._ops_request( method=http_methods.PUT, path=f"/databases/{database}/access-list", @@ -146,6 +288,16 @@ def replace_access_list(self, database="", access_list=None): ).json() def update_access_list(self, database="", access_list=None): + """ + Update the access list for a specific database. + + Args: + database (str): The identifier of the database for which to update the access list. + access_list (dict): The updates to be applied to the access list. + + Returns: + dict: The response from the server after updating the access list. + """ return self._ops_request( method=http_methods.PATCH, path=f"/databases/{database}/access-list", @@ -153,6 +305,16 @@ def update_access_list(self, database="", access_list=None): ).json() def add_access_list_address(self, database="", address=None): + """ + Add a new address to the access list for a specific database. + + Args: + database (str): The identifier of the database for which to add the address. + address (dict): The address details to add to the access list. + + Returns: + dict: The response from the server after adding the address. + """ return self._ops_request( method=http_methods.POST, path=f"/databases/{database}/access-list", @@ -160,18 +322,46 @@ def add_access_list_address(self, database="", address=None): ).json() def delete_access_list(self, database=""): + """ + Delete the access list for a specific database. + + Args: + database (str): The identifier of the database for which to delete the access list. + + Returns: + dict: The response from the server after deleting the access list. + """ return self._ops_request( method=http_methods.DELETE, path=f"/databases/{database}/access-list", ).json() def get_private_link(self, database=""): + """ + Retrieve the private link information for a specified database. + + Args: + database (str): The identifier of the database. + + Returns: + dict: The private link information for the database. + """ return self._ops_request( method=http_methods.GET, path=f"/organizations/clusters/{database}/private-link", ).json() def get_datacenter_private_link(self, database="", datacenter=""): + """ + Retrieve the private link information for a specific datacenter in a database. + + Args: + database (str): The identifier of the database. + datacenter (str): The identifier of the datacenter. + + Returns: + dict: The private link information for the specified datacenter. + """ return self._ops_request( method=http_methods.GET, path=f"/organizations/clusters/{database}/datacenters/{datacenter}/private-link", @@ -180,6 +370,17 @@ def get_datacenter_private_link(self, database="", datacenter=""): def create_datacenter_private_link( self, database="", datacenter="", private_link=None ): + """ + Create a private link for a specific datacenter in a database. + + Args: + database (str): The identifier of the database. + datacenter (str): The identifier of the datacenter. + private_link (dict): The private link configuration details. + + Returns: + dict: The response from the server after creating the private link. + """ return self._ops_request( method=http_methods.POST, path=f"/organizations/clusters/{database}/datacenters/{datacenter}/private-link", @@ -187,6 +388,17 @@ def create_datacenter_private_link( ).json() def create_datacenter_endpoint(self, database="", datacenter="", endpoint=None): + """ + Create an endpoint for a specific datacenter in a database. + + Args: + database (str): The identifier of the database. + datacenter (str): The identifier of the datacenter. + endpoint (dict): The endpoint configuration details. + + Returns: + dict: The response from the server after creating the endpoint. + """ return self._ops_request( method=http_methods.POST, path=f"/organizations/clusters/{database}/datacenters/{datacenter}/endpoint", @@ -194,6 +406,17 @@ def create_datacenter_endpoint(self, database="", datacenter="", endpoint=None): ).json() def update_datacenter_endpoint(self, database="", datacenter="", endpoint=None): + """ + Update an existing endpoint for a specific datacenter in a database. + + Args: + database (str): The identifier of the database. + datacenter (str): The identifier of the datacenter. + endpoint (dict): The updated endpoint configuration details. + + Returns: + dict: The response from the server after updating the endpoint. + """ return self._ops_request( method=http_methods.PUT, path=f"/organizations/clusters/{database}/datacenters/{datacenter}/endpoints/{endpoint['id']}", @@ -201,33 +424,82 @@ def update_datacenter_endpoint(self, database="", datacenter="", endpoint=None): ).json() def get_datacenter_endpoint(self, database="", datacenter="", endpoint=""): + """ + Retrieve information about a specific endpoint in a datacenter of a database. + + Args: + database (str): The identifier of the database. + datacenter (str): The identifier of the datacenter. + endpoint (str): The identifier of the endpoint. + + Returns: + dict: The endpoint information for the specified datacenter. + """ return self._ops_request( method=http_methods.GET, path=f"/organizations/clusters/{database}/datacenters/{datacenter}/endpoints/{endpoint}", ).json() def delete_datacenter_endpoint(self, database="", datacenter="", endpoint=""): + """ + Delete a specific endpoint in a datacenter of a database. + + Args: + database (str): The identifier of the database. + datacenter (str): The identifier of the datacenter. + endpoint (str): The identifier of the endpoint to delete. + + Returns: + dict: The response from the server after deleting the endpoint. + """ return self._ops_request( method=http_methods.DELETE, path=f"/organizations/clusters/{database}/datacenters/{datacenter}/endpoints/{endpoint}", ).json() def get_available_classic_regions(self): + """ + Retrieve a list of available classic regions. + + Returns: + dict: A list of available classic regions. + """ return self._ops_request( method=http_methods.GET, path=f"/availableRegions" ).json() def get_available_regions(self): + """ + Retrieve a list of available regions for serverless deployment. + + Returns: + dict: A list of available regions for serverless deployment. + """ return self._ops_request( method=http_methods.GET, path=f"/regions/serverless" ).json() def get_roles(self): + """ + Retrieve a list of roles within the organization. + + Returns: + dict: A list of roles within the organization. + """ return self._ops_request( method=http_methods.GET, path=f"/organizations/roles" ).json() def create_role(self, role_definition=None): + """ + Create a new role within the organization. + + Args: + role_definition (dict, optional): The definition of the role to be created. + + Returns: + dict: The response from the server after creating the role. + """ return self._ops_request( method=http_methods.POST, path=f"/organizations/roles", @@ -235,11 +507,30 @@ def create_role(self, role_definition=None): ).json() def get_role(self, role=""): + """ + Retrieve details of a specific role within the organization. + + Args: + role (str): The identifier of the role. + + Returns: + dict: The details of the specified role. + """ return self._ops_request( method=http_methods.GET, path=f"/organizations/roles/{role}" ).json() def update_role(self, role="", role_definition=None): + """ + Update the definition of an existing role within the organization. + + Args: + role (str): The identifier of the role to update. + role_definition (dict, optional): The new definition of the role. + + Returns: + dict: The response from the server after updating the role. + """ return self._ops_request( method=http_methods.PUT, path=f"/organizations/roles/{role}", @@ -247,11 +538,29 @@ def update_role(self, role="", role_definition=None): ).json() def delete_role(self, role=""): + """ + Delete a specific role from the organization. + + Args: + role (str): The identifier of the role to delete. + + Returns: + dict: The response from the server after deleting the role. + """ return self._ops_request( method=http_methods.DELETE, path=f"/organizations/roles/{role}" ).json() def invite_user(self, user_definition=None): + """ + Invite a new user to the organization. + + Args: + user_definition (dict, optional): The definition of the user to be invited. + + Returns: + dict: The response from the server after inviting the user. + """ return self._ops_request( method=http_methods.PUT, path=f"/organizations/users", @@ -259,21 +568,55 @@ def invite_user(self, user_definition=None): ).json() def get_users(self): + """ + Retrieve a list of users within the organization. + + Returns: + dict: A list of users within the organization. + """ return self._ops_request( method=http_methods.GET, path=f"/organizations/users" ).json() def get_user(self, user=""): + """ + Retrieve details of a specific user within the organization. + + Args: + user (str): The identifier of the user. + + Returns: + dict: The details of the specified user. + """ return self._ops_request( method=http_methods.GET, path=f"/organizations/users/{user}" ).json() def remove_user(self, user=""): + """ + Remove a user from the organization. + + Args: + user (str): The identifier of the user to remove. + + Returns: + dict: The response from the server after removing the user. + """ return self._ops_request( method=http_methods.DELETE, path=f"/organizations/users/{user}" ).json() def update_user_roles(self, user="", roles=None): + """ + Update the roles assigned to a specific user within the organization. + + Args: + user (str): The identifier of the user. + roles (list, optional): The list of new roles to assign to the user. + + Returns: + dict: The response from the server after updating the user's roles. + """ return self._ops_request( method=http_methods.PUT, path=f"/organizations/users/{user}/roles", @@ -281,11 +624,26 @@ def update_user_roles(self, user="", roles=None): ).json() def get_clients(self): + """ + Retrieve a list of client IDs and secrets associated with the organization. + + Returns: + dict: A list of client IDs and their associated secrets. + """ return self._ops_request( method=http_methods.GET, path=f"/clientIdSecrets" ).json() def create_token(self, roles=None): + """ + Create a new token with specific roles. + + Args: + roles (list, optional): The roles to associate with the token. + + Returns: + dict: The response from the server after creating the token. + """ return self._ops_request( method=http_methods.POST, path=f"/clientIdSecrets", @@ -293,42 +651,102 @@ def create_token(self, roles=None): ).json() def delete_token(self, token=""): + """ + Delete a specific token. + + Args: + token (str): The identifier of the token to delete. + + Returns: + dict: The response from the server after deleting the token. + """ return self._ops_request( method=http_methods.DELETE, path=f"/clientIdSecret/{token}" ).json() def get_organization(self): + """ + Retrieve details of the current organization. + + Returns: + dict: The details of the organization. + """ return self._ops_request(method=http_methods.GET, path=f"/currentOrg").json() def get_access_lists(self): + """ + Retrieve a list of access lists for the organization. + + Returns: + dict: A list of access lists. + """ return self._ops_request(method=http_methods.GET, path=f"/access-lists").json() def get_access_list_template(self): + """ + Retrieve a template for creating an access list. + + Returns: + dict: An access list template. + """ return self._ops_request( method=http_methods.GET, path=f"/access-list/template" ).json() def validate_access_list(self): + """ + Validate the configuration of the access list. + + Returns: + dict: The validation result of the access list configuration. + """ return self._ops_request( method=http_methods.POST, path=f"/access-list/validate" ).json() def get_private_links(self): + """ + Retrieve a list of private link connections for the organization. + + Returns: + dict: A list of private link connections. + """ return self._ops_request( method=http_methods.GET, path=f"/organizations/private-link" ).json() def get_streaming_providers(self): + """ + Retrieve a list of streaming service providers. + + Returns: + dict: A list of available streaming service providers. + """ return self._ops_request( method=http_methods.GET, path=f"/streaming/providers" ).json() def get_streaming_tenants(self): + """ + Retrieve a list of streaming tenants. + + Returns: + dict: A list of streaming tenants and their details. + """ return self._ops_request( method=http_methods.GET, path=f"/streaming/tenants" ).json() def create_streaming_tenant(self, tenant=None): + """ + Create a new streaming tenant. + + Args: + tenant (dict, optional): The configuration details for the new streaming tenant. + + Returns: + dict: The response from the server after creating the streaming tenant. + """ return self._ops_request( method=http_methods.POST, path=f"/streaming/tenants", @@ -336,6 +754,16 @@ def create_streaming_tenant(self, tenant=None): ).json() def delete_streaming_tenant(self, tenant="", cluster=""): + """ + Delete a specific streaming tenant from a cluster. + + Args: + tenant (str): The identifier of the tenant to delete. + cluster (str): The identifier of the cluster from which the tenant is to be deleted. + + Returns: + dict: The response from the server after deleting the streaming tenant. + """ return self._ops_request( method=http_methods.DELETE, path=f"/streaming/tenants/{tenant}/clusters/{cluster}", @@ -343,6 +771,15 @@ def delete_streaming_tenant(self, tenant="", cluster=""): ).json() def get_streaming_tenant(self, tenant=""): + """ + Retrieve information about the limits and usage of a specific streaming tenant. + + Args: + tenant (str): The identifier of the streaming tenant. + + Returns: + dict: Details of the specified streaming tenant, including limits and current usage. + """ return self._ops_request( method=http_methods.GET, path=f"/streaming/tenants/{tenant}/limits", diff --git a/astrapy/utils.py b/astrapy/utils.py index 450da878..ee0789b8 100644 --- a/astrapy/utils.py +++ b/astrapy/utils.py @@ -21,6 +21,13 @@ class http_methods: def log_request_response(r, json_data): + """ + Log the details of an HTTP request and its response for debugging purposes. + + Args: + r (requests.Response): The response object from the HTTP request. + json_data (dict or None): The JSON payload sent with the request, if any. + """ logger.debug(f"Request URL: {r.url}") logger.debug(f"Request method: {r.request.method}") logger.debug(f"Request headers: {r.request.headers}") @@ -42,6 +49,21 @@ def make_request( json_data=None, url_params=None, ): + """ + Make an HTTP request to a specified URL. + + Args: + base_url (str): The base URL for the request. + auth_header (str): The authentication header key. + token (str): The token used for authentication. + method (str, optional): The HTTP method to use for the request. Default is POST. + path (str, optional): The specific path to append to the base URL. + json_data (dict, optional): JSON payload to be sent with the request. + url_params (dict, optional): URL parameters to be sent with the request. + + Returns: + requests.Response: The response from the HTTP request. + """ r = requests.request( method=method, url=f"{base_url}{path}", @@ -58,6 +80,16 @@ def make_request( def make_payload(top_level, **kwargs): + """ + Construct a JSON payload for an HTTP request with a specified top-level key. + + Args: + top_level (str): The top-level key for the JSON payload. + **kwargs: Arbitrary keyword arguments representing other keys and their values to be included in the payload. + + Returns: + dict: The constructed JSON payload. + """ params = {} for key, value in kwargs.items(): params[key] = value