-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add the cloud.client and cloud.application logic
- Loading branch information
1 parent
ca6ac17
commit c3c983f
Showing
11 changed files
with
241 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
"""Functionality for interacting with the Nextmv Cloud.""" | ||
|
||
from .application import Application as Application | ||
from .client import Client as Client |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
"""This module contains the application class.""" | ||
|
||
from dataclasses import dataclass | ||
from datetime import datetime | ||
from typing import Any | ||
|
||
from nextmv.cloud.client import Client | ||
from nextmv.json_class import JSONClass | ||
|
||
|
||
@dataclass | ||
class Metadata(JSONClass): | ||
"""Metadata of a run, whether it was successful or not.""" | ||
|
||
status: str | ||
"""Status of the run.""" | ||
created_at: datetime | ||
"""Date and time when the run was created.""" | ||
duration: float | ||
"""Duration of the run in milliseconds.""" | ||
input_size: float | ||
"""Size of the input in bytes.""" | ||
output_size: float | ||
"""Size of the output in bytes.""" | ||
error: str | ||
"""Error message if the run failed.""" | ||
application_id: str | ||
"""ID of the application where the run was submitted to.""" | ||
application_instance_id: str | ||
"""ID of the instance where the run was submitted to.""" | ||
application_version_id: str | ||
"""ID of the version of the application where the run was submitted to.""" | ||
|
||
|
||
@dataclass | ||
class RunResult(JSONClass): | ||
"""Result of a run, wheter it was successful or not.""" | ||
|
||
id: str | ||
"""ID of the run.""" | ||
user_email: str | ||
"""Email of the user who submitted the run.""" | ||
name: str | ||
"""Name of the run.""" | ||
description: str | ||
"""Description of the run.""" | ||
metadata: Metadata | ||
"""Metadata of the run.""" | ||
output: dict[str, Any] | ||
"""Output of the run.""" | ||
|
||
|
||
@dataclass | ||
class Application: | ||
"""An application is a published decision model that can be executed.""" | ||
|
||
client: Client | ||
"""Client to use for interacting with the Nextmv Cloud API.""" | ||
id: str | ||
"""ID of the application.""" | ||
endpoint: str = "v1/applications/{id}" | ||
"""Base endpoint for the application.""" | ||
default_instance_id: str = "devint" | ||
"""Default instance ID to use for submitting runs.""" | ||
|
||
def __post_init__(self): | ||
"""Logic to run after the class is initialized.""" | ||
|
||
self.endpoint = self.endpoint.format(id=self.id) | ||
|
||
def new_run( | ||
self, | ||
input: dict[str, Any] = None, | ||
instance_id: str | None = None, | ||
name: str | None = None, | ||
description: str | None = None, | ||
upload_id: str | None = None, | ||
options: dict[str, Any] | None = None, | ||
) -> str: | ||
""" | ||
Submit an input to start a new run of the application. Returns the | ||
run_id of the submitted run. | ||
Args: | ||
input: Input to use for the run. | ||
instance_id: ID of the instance to use for the run. If not | ||
provided, the default_instance_id will be used. | ||
name: Name of the run. | ||
description: Description of the run. | ||
upload_id: ID to use when running a large input. | ||
options: Options to use for the run. | ||
""" | ||
|
||
payload = { | ||
"input": input, | ||
} | ||
if name is not None: | ||
payload["name"] = name | ||
if description is not None: | ||
payload["description"] = description | ||
if upload_id is not None: | ||
payload["upload_id"] = upload_id | ||
if options is not None: | ||
payload["options"] = options | ||
|
||
query_params = { | ||
"instance_id": instance_id if instance_id is not None else self.default_instance_id, | ||
} | ||
response = self.client.post( | ||
endpoint=f"{self.endpoint}/runs", | ||
payload=payload, | ||
query_params=query_params, | ||
) | ||
response.raise_for_status() | ||
|
||
return response.json()["run_id"] | ||
|
||
def run_result( | ||
self, | ||
run_id: str, | ||
) -> RunResult: | ||
""" | ||
Get the result of a run. | ||
Args: | ||
run_id: ID of the run. | ||
""" | ||
|
||
response = self.client.get( | ||
endpoint=f"{self.endpoint}/runs/{run_id}", | ||
) | ||
response.raise_for_status() | ||
|
||
return RunResult.from_dict(response.json()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
"""Module with the client class.""" | ||
|
||
import os | ||
from dataclasses import dataclass | ||
from typing import Any | ||
|
||
import requests | ||
|
||
|
||
@dataclass | ||
class Client: | ||
"""Client that interacts directly with the Nextmv Cloud API. The API key | ||
must be provided either in the constructor or via the NEXTMV_API_KEY""" | ||
|
||
api_key: str | None = None | ||
"""API key to use for authenticating with the Nextmv Cloud API. If not | ||
provided, the client will look for the NEXTMV_API_KEY environment | ||
variable.""" | ||
url: str = "https://api.cloud.nextmv.io" | ||
"""URL of the Nextmv Cloud API.""" | ||
headers: dict[str, str] | None = None | ||
"""Headers to use for requests to the Nextmv Cloud API.""" | ||
|
||
def __post_init__(self): | ||
"""Logic to run after the class is initialized.""" | ||
|
||
if self.api_key is None: | ||
api_key = os.getenv("NEXTMV_API_KEY") | ||
if api_key is None: | ||
raise ValueError( | ||
"no API key provided. Either set it in the constructor or " | ||
"set the NEXTMV_API_KEY environment variable." | ||
) | ||
self.api_key = api_key | ||
|
||
self.headers = { | ||
"Authorization": f"Bearer {self.api_key}", | ||
"Content-Type": "application/json", | ||
} | ||
|
||
def post( | ||
self, | ||
endpoint: str, | ||
payload: dict[str, Any], | ||
query_params: dict[str, Any] | None = None, | ||
) -> requests.Response: | ||
"""Send a POST request to the Nextmv Cloud API.""" | ||
|
||
return requests.post( | ||
url=f"{self.url}/{endpoint}", | ||
json=payload, | ||
headers=self.headers, | ||
params=query_params, | ||
) | ||
|
||
def get( | ||
self, | ||
endpoint: str, | ||
query_params: dict[str, Any] | None = None, | ||
) -> requests.Response: | ||
"""Send a GET request to the Nextmv Cloud API.""" | ||
|
||
return requests.get( | ||
url=f"{self.url}/{endpoint}", | ||
headers=self.headers, | ||
params=query_params, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
requests==2.31.0 | ||
ruff==0.1.7 | ||
setuptools==69.0.2 | ||
wheel==0.42.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters