diff --git a/docs/conf.py b/docs/conf.py index 4aefe2c..61a7cce 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -24,9 +24,13 @@ extensions = [ "sphinx.ext.autosummary", "sphinx.ext.intersphinx", "sphinx.ext.autosectionlabel", + # "sphinx_immaterial", ] +# html_theme = "sphinx_immaterial" +html_theme_options = {} -autodoc_typehints = "signature" + +# autodoc_typehints = "signature" templates_path = ["_templates"] exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] diff --git a/neon_client/client.py b/neon_client/client.py index 961cfa7..5aa0452 100644 --- a/neon_client/client.py +++ b/neon_client/client.py @@ -7,7 +7,7 @@ import requests from . import schema from .utils import compact_mapping, to_iso8601 -from .exceptions import NeonAPIException +from .exceptions import NeonAPIError __VERSION__ = "0.1.0" @@ -20,6 +20,10 @@ ENABLE_PYDANTIC = True def returns_model(model, is_array=False): """Decorator that returns a Pydantic dataclass. + :param model: The Pydantic dataclass to return. + :param is_array: Whether the return value is an array (default is False). + :return: A Pydantic dataclass. + If Pydantic is not enabled, the original return value is returned. """ @@ -40,7 +44,11 @@ def returns_model(model, is_array=False): def returns_subkey(key): - """Decorator that returns a subkey.""" + """Decorator that returns a subkey. + + :param key: The key to return. + :return: The value of the key in the return value. + """ def decorator(func): @wraps(func) @@ -57,7 +65,11 @@ def returns_subkey(key): class NeonAPI: def __init__(self, api_key: str, *, base_url: str = None): - """A Neon API client.""" + """A Neon API client. + + :param api_key: The API key to use for authentication. + :param base_url: The base URL of the Neon API (default is https://console.neon.tech/api/v2/). + """ # Set the base URL. if not base_url: @@ -80,7 +92,13 @@ class NeonAPI: path: str, **kwargs, ): - """Send an HTTP request to the specified API path using the specified method.""" + """Send an HTTP request to the specified API path using the specified method. + + :param method: The HTTP method to use (e.g., "GET", "POST", "PUT", "DELETE"). + :param path: The API path to send the request to. + :param kwargs: Additional keyword arguments to pass to the requests.Session.request method. + :return: The JSON response from the server. + """ # Set HTTP headers for outgoing requests. headers = kwargs.pop("headers", {}) @@ -98,7 +116,7 @@ class NeonAPI: try: r.raise_for_status() except requests.exceptions.HTTPError: - raise NeonAPIException(r.text) + raise NeonAPIError(r.text) return r.json() @@ -126,6 +144,8 @@ class NeonAPI: def api_keys(self) -> t.List[t.Dict[str, t.Any]]: """Get a list of API keys. + :return: A dataclass representing the API key. + More info: https://api-docs.neon.tech/reference/listapikeys """ @@ -135,6 +155,9 @@ class NeonAPI: def api_key_create(self, **json: dict) -> t.Dict[str, t.Any]: """Create a new API key. + :param json: The JSON paypload to send to the server. + :return: A dataclass representing the API key. + Example usage: ```python @@ -184,6 +207,9 @@ class NeonAPI: def project(self, project_id: str) -> t.Dict[str, t.Any]: """Get a project. + :param project_id: The ID of the project. + :return: A dataclass representing the project. + More info: https://api-docs.neon.tech/reference/getproject """ @@ -195,6 +221,9 @@ class NeonAPI: def project_create(self, **json: dict) -> t.Dict[str, t.Any]: """Create a new project. Accepts all keyword arguments for json body. + :param json: The JSON paypload to send to the server. + :return: A dataclass representing the project. + More info: https://api-docs.neon.tech/reference/createproject """ @@ -204,6 +233,10 @@ class NeonAPI: def project_update(self, project_id: str, **json: dict) -> t.Dict[str, t.Any]: """Updates a project. Accepts all keyword arguments for json body. + :param project_id: The ID of the project. + :param json: The JSON paypload to send to the server. + :return: A dataclass representing the project. + More info: https://api-docs.neon.tech/reference/updateproject""" return self._request("PATCH", f"projects/{ project_id }", json=json) @@ -212,6 +245,9 @@ class NeonAPI: def project_delete(self, project_id: str) -> t.Dict[str, t.Any]: """Delete a project. + :param project_id: The ID of the project. + :return: A dataclass representing the project. + More info: https://api-docs.neon.tech/reference/deleteproject """ @@ -221,6 +257,9 @@ class NeonAPI: def project_permissions(self, project_id: str) -> t.Dict[str, t.Any]: """Get a project permissions. + :param project_id: The ID of the project. + :return: A dataclass representing the project permissions. + More info: https://api-docs.neon.tech/reference/listprojectpermissions """ return self._request("GET", f"projects/{ project_id }/permissions") @@ -231,6 +270,10 @@ class NeonAPI: ) -> t.Dict[str, t.Any]: """Update a project permissions. Accepts all keyword arguments for json body. + :param project_id: The ID of the project. + :param json: The JSON paypload to send to the server. + :return: A dataclass representing the project permissions. + More info: https://api-docs.neon.tech/reference/grantpermissiontoproject """ return self._request("POST", f"projects/{ project_id }/permissions", json=json) @@ -241,6 +284,10 @@ class NeonAPI: ) -> t.Dict[str, t.Any]: """Update a project permissions. Accepts all keyword arguments for json body. + :param project_id: The ID of the project. + :param json: The JSON paypload to send to the server. + :return: A dataclass representing the project permissions. + More info: https://api-docs.neon.tech/reference/revokepermissionfromproject """ return self._request( @@ -257,6 +304,11 @@ class NeonAPI: ) -> t.Dict[str, t.Any]: """Get a list of branches. + :param project_id: The ID of the project. + :param cursor: The cursor for pagination (default is None). + :param limit: The maximum number of projects to retrieve (default is None). + :return: A list of dataclasses representing the projects. + More info: https://api-docs.neon.tech/reference/listprojectbranches """ @@ -271,6 +323,10 @@ class NeonAPI: def branch(self, project_id: str, branch_id: str) -> t.Dict[str, t.Any]: """Get a branch. + :param project_id: The ID of the project. + :param branch_id: The ID of the branch. + :return: A dataclass representing the branch. + More info: https://api-docs.neon.tech/reference/getprojectbranch """ @@ -284,6 +340,10 @@ class NeonAPI: def branch_create(self, project_id: str, **json: dict) -> t.Dict[str, t.Any]: """Create a new branch. Accepts all keyword arguments for json body. + :param project_id: The ID of the project. + :param json: The JSON paypload to send to the server. + :return: A dataclass representing the branch. + More info: https://api-docs.neon.tech/reference/createprojectbranch """ return self._request("POST", f"projects/{ project_id }/branches", json=json) @@ -294,6 +354,11 @@ class NeonAPI: ) -> t.Dict[str, t.Any]: """Update a branch by branch_id. Accepts all keyword arguments for json body. + :param project_id: The ID of the project. + :param branch_id: The ID of the branch. + :param json: The JSON paypload to send to the server. + :return: A dataclass representing the branch. + More info: https://api-docs.neon.tech/reference/updateprojectbranch """ @@ -305,6 +370,10 @@ class NeonAPI: def branch_delete(self, project_id: str, branch_id: str) -> t.Dict[str, t.Any]: """Delete a branch by branch_id. + :param project_id: The ID of the project. + :param branch_id: The ID of the branch. + :return: A dataclass representing the branch. + More info: https://api-docs.neon.tech/reference/deleteprojectbranch """ return self._request( @@ -317,6 +386,10 @@ class NeonAPI: ) -> t.Dict[str, t.Any]: """Set a branch as primary by branch_id. + :param project_id: The ID of the project. + :param branch_id: The ID of the branch. + :return: A dataclass representing the branch. + More info: https://api-docs.neon.tech/reference/setprimaryprojectbranch""" return self._request( @@ -331,9 +404,15 @@ class NeonAPI: *, cursor: str | None = None, limit: int | None = None, - ) -> t.Dict[str, t.Any]: + ) -> t.List[t.Dict[str, t.Any]]: """Get a list of databases. + :param project_id: The ID of the project. + :param branch_id: The ID of the branch. + :param cursor: The cursor for pagination (default is None). + :param limit: The maximum number of projects to retrieve (default is None). + :return: A list of dataclasses representing the database. + More info: https://api-docs.neon.tech/reference/listprojectbranchdatabases """ @@ -352,6 +431,11 @@ class NeonAPI: ) -> t.Dict[str, t.Any]: """Get a database. + :param project_id: The ID of the project. + :param branch_id: The ID of the branch. + :param database_id: The ID of the database. + :return: A dataclass representing the database. + More info: https://api-docs.neon.tech/reference/getprojectbranchdatabase """ @@ -369,6 +453,11 @@ class NeonAPI: ) -> t.Dict[str, t.Any]: """Create a new database. Accepts all keyword arguments for json body. + :param project_id: The ID of the project. + :param branch_id: The ID of the branch. + :param json: The JSON paypload to send to the server. + :return: A dataclass representing the database. + More info: https://api-docs.neon.tech/reference/createprojectbranchdatabase """ @@ -384,6 +473,12 @@ class NeonAPI: ) -> t.Dict[str, t.Any]: """Update a database. Accepts all keyword arguments for json body. + :param project_id: The ID of the project. + :param branch_id: The ID of the branch. + :param database_id: The ID of the database. + :param json: The JSON paypload to send to the server. + :return: A dataclass representing the database. + More info: https://api-docs.neon.tech/reference/updateprojectbranchdatabase """ @@ -399,6 +494,11 @@ class NeonAPI: ) -> t.Dict[str, t.Any]: """Delete a database by database_id. + :param project_id: The ID of the project. + :param branch_id: The ID of the branch. + :param database_id: The ID of the database. + :return: A dataclass representing the database. + More info: https://api-docs.neon.tech/reference/deleteprojectbranchdatabase """ @@ -411,6 +511,9 @@ class NeonAPI: def endpoints(self, project_id: str) -> t.Dict[str, t.Any]: """Get a list of endpoints for a given branch + :param project_id: The ID of the project. + :return: A list of dataclasses representing the endpoints. + More info: https://api-docs.neon.tech/reference/listprojectendpoints """ return self._request("GET", f"projects/{ project_id }/endpoints") @@ -419,6 +522,10 @@ class NeonAPI: def endpoint(self, project_id: str, endpoint_id: str) -> t.Dict[str, t.Any]: """Get an endpoint for a given branch. + :param project_id: The ID of the project. + :param endpoint_id: The ID of the endpoint. + :return: A dataclass representing the endpoint. + More info: https://api-docs.neon.tech/reference/getprojectendpoint """ return self._request( @@ -434,6 +541,10 @@ class NeonAPI: ) -> t.Dict[str, t.Any]: """Create a new endpoint. Accepts all keyword arguments for json body. + :param project_id: The ID of the project. + :param json: The JSON paypload to send to the server. + :return: A dataclass representing the endpoint. + More info: https://api-docs.neon.tech/reference/createprojectendpoint """ @@ -443,6 +554,10 @@ class NeonAPI: def endpoint_delete(self, project_id: str, endpoint_id: str) -> t.Dict[str, t.Any]: """Delete an endpoint by endpoint_id. + :param project_id: The ID of the project. + :param endpoint_id: The ID of the endpoint. + :return: A dataclass representing the endpoint. + More info: https://api-docs.neon.tech/reference/deleteprojectendpoint """ @@ -457,6 +572,11 @@ class NeonAPI: ) -> t.Dict[str, t.Any]: """Update an endpoint. Accepts all keyword arguments for json body. + :param project_id: The ID of the project. + :param endpoint_id: The ID of the endpoint. + :param json: The JSON paypload to send to the server. + :return: A dataclass representing the endpoint. + More info: https://api-docs.neon.tech/reference/updateprojectendpoint """ @@ -470,6 +590,10 @@ class NeonAPI: def endpoint_start(self, project_id: str, endpoint_id: str): """Start an endpoint by endpoint_id. + :param project_id: The ID of the project. + :param endpoint_id: The ID of the endpoint. + :return: A dataclass representing the endpoint. + More info: https://api-docs.neon.tech/reference/startprojectendpoint""" return self._request( @@ -481,6 +605,10 @@ class NeonAPI: def endpoint_suspend(self, project_id: str, endpoint_id: str): """Suspend an endpoint by endpoint_id. + :param project_id: The ID of the project. + :param endpoint_id: The ID of the endpoint. + :return: A dataclass representing the endpoint. + More info: https://api-docs.neon.tech/reference/suspendprojectendpoint """ @@ -493,6 +621,10 @@ class NeonAPI: def roles(self, project_id: str, branch_id: str) -> t.Dict[str, t.Any]: """Get a list of roles for a given branch. + :param project_id: The ID of the project. + :param branch_id: The ID of the branch. + :return: A list of dataclasses representing the roles. + More info: https://api-docs.neon.tech/reference/listprojectbranchroles """ @@ -506,6 +638,11 @@ class NeonAPI: ) -> t.Dict[str, t.Any]: """Get a role for a given branch. + :param project_id: The ID of the project. + :param branch_id: The ID of the branch. + :param role_name: The name of the role. + :return: A dataclass representing the role. + More info: https://api-docs.neon.tech/reference/getprojectbranchrole """ @@ -522,6 +659,11 @@ class NeonAPI: ) -> t.Dict[str, t.Any]: """Create a new role. Accepts all keyword arguments for json body. + :param project_id: The ID of the project. + :param branch_id: The ID of the branch. + :param role_name: The name of the role. + :return: A dataclass representing the role. + More info: https://api-docs.neon.tech/reference/createprojectbranchrole """ @@ -540,6 +682,11 @@ class NeonAPI: ) -> t.Dict[str, t.Any]: """Delete a role by given role name. + :param project_id: The ID of the project. + :param branch_id: The ID of the branch. + :param role_name: The name of the role. + :return: A dataclass representing the role. + More info: https://api-docs.neon.tech/reference/deleteprojectbranchrole """ @@ -557,6 +704,11 @@ class NeonAPI: ) -> t.Dict[str, t.Any]: """Get a role password. + :param project_id: The ID of the project. + :param branch_id: The ID of the branch. + :param role_name: The name of the role. + :return: A dataclass representing the role password. + More info: https://api-docs.neon.tech/reference/getprojectbranchrolepassword""" return self._request( @@ -573,6 +725,11 @@ class NeonAPI: ) -> t.Dict[str, t.Any]: """Reset a role password. + :param project_id: The ID of the project. + :param branch_id: The ID of the branch. + :param role_name: The name of the role. + :return: A dataclass representing the role. + More info: https://api-docs.neon.tech/reference/resetprojectbranchrolepassword """ @@ -591,6 +748,11 @@ class NeonAPI: ) -> t.Dict[str, t.Any]: """Get a list of operations. + :param project_id: The ID of the project. + :param cursor: The cursor for pagination (default is None). + :param limit: The maximum number of projects to retrieve (default is None). + :return: A list of dataclasses representing the operations. + More info: https://api-docs.neon.tech/reference/listprojectoperations """ @@ -603,6 +765,10 @@ class NeonAPI: def operation(self, project_id: str, operation_id: str) -> t.Dict[str, t.Any]: """Get an operation. + :param project_id: The ID of the project. + :param operation_id: The ID of the operation. + :return: A dataclass representing the operation. + More info: https://api-docs.neon.tech/reference/getprojectoperation """ @@ -621,6 +787,12 @@ class NeonAPI: ) -> t.Dict[str, t.Any]: """Experimental — get a list of consumption metrics for all projects. + :param cursor: The cursor for pagination (default is None). + :param limit: The maximum number of projects to retrieve (default is None). + :param from_date: The start date for the consumption metrics (default is None). + :param to_date: The end date for the consumption metrics (default is None). + :return: A dataclass representing the consumption metrics. + More info: https://api-docs.neon.tech/reference/listprojectsconsumption """ diff --git a/neon_client/exceptions.py b/neon_client/exceptions.py index 3a12003..ccb5416 100644 --- a/neon_client/exceptions.py +++ b/neon_client/exceptions.py @@ -1,5 +1,5 @@ from requests.exceptions import HTTPError -class NeonAPIException(HTTPError): +class NeonAPIError(HTTPError): pass