Skip to content

Commit af9083f

Browse files
Merge branch 'feature/eng-4278-complete-cloud-api' into feature/eng-4277-create-workflow-for-publishingdistributing-the-package
2 parents 8f21c03 + e24807e commit af9083f

File tree

4 files changed

+24
-38
lines changed

4 files changed

+24
-38
lines changed

nextmv/cloud/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
"""Functionality for interacting with the Nextmv Cloud."""
22

33
from .acceptance_test import AcceptanceTest as AcceptanceTest
4-
from .acceptance_test import AcceptanceTestParams as AcceptanceTestParams
54
from .acceptance_test import Comparison as Comparison
65
from .acceptance_test import ComparisonInstance as ComparisonInstance
76
from .acceptance_test import Metric as Metric
7+
from .acceptance_test import MetricParams as MetricParams
88
from .acceptance_test import MetricType as MetricType
99
from .application import Application as Application
1010
from .application import DownloadURL as DownloadURL

nextmv/cloud/acceptance_test.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class Comparison(str, Enum):
3434
"""Not equal to metric type."""
3535

3636

37-
class AcceptanceTestParams(BaseModel):
37+
class MetricParams(BaseModel):
3838
"""Parameters of an acceptance test."""
3939

4040
operator: Comparison
@@ -49,14 +49,14 @@ class Metric(BaseModel):
4949
"""Field of the metric."""
5050
metric_type: MetricType
5151
"""Type of the metric."""
52-
params: AcceptanceTestParams
52+
params: MetricParams
5353
"""Parameters of the metric."""
5454
statistic: str
5555
"""Statistic of the metric."""
5656

5757

5858
class ComparisonInstance(BaseModel):
59-
"""An instance used for a comparison."""
59+
"""An app instance used for a comparison."""
6060

6161
instance_id: str
6262
"""ID of the instance."""

nextmv/cloud/application.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
from nextmv.cloud.client import Client, get_size
1212
from nextmv.cloud.input_set import InputSet
1313

14+
_MAX_RUN_SIZE: int = 5 * 1024 * 1024
15+
"""Maximum size of the run input/output. This value is used to determine
16+
whether to use the large input upload and/or result download endpoints."""
17+
1418

1519
class DownloadURL(BaseModel):
1620
"""Result of getting a download URL."""
@@ -122,9 +126,6 @@ class Application:
122126
"""Base endpoint for the application."""
123127
experiments_endpoint: str = "{base}/experiments"
124128
"""Base endpoint for the experiments in the application."""
125-
max_run_size: int = 5 * 1024 * 1024
126-
"""Maximum size of the run input/output. This value is used to determine
127-
whether to use the large input upload and/or result download endpoints."""
128129

129130
def __post_init__(self):
130131
"""Logic to run after the class is initialized."""
@@ -470,7 +471,7 @@ def new_run(
470471
input_size = get_size(input)
471472

472473
upload_id_used = upload_id is not None
473-
if not upload_id_used and input_size > self.max_run_size:
474+
if not upload_id_used and input_size > _MAX_RUN_SIZE:
474475
upload_url = self.upload_url()
475476
self.upload_large_input(upload_url=upload_url, input=input)
476477
upload_id = upload_url.upload_id
@@ -509,7 +510,7 @@ def new_run_with_result(
509510
description: str | None = None,
510511
upload_id: str | None = None,
511512
run_options: dict[str, Any] | None = None,
512-
polling_options: PollingOptions | None = None,
513+
polling_options: PollingOptions = None,
513514
) -> RunResult:
514515
"""
515516
Submit an input to start a new run of the application and poll for the
@@ -703,7 +704,7 @@ def _run_result(
703704
"""
704705
query_params = None
705706
large_output = False
706-
if run_information.metadata.output_size > self.max_run_size:
707+
if run_information.metadata.output_size > _MAX_RUN_SIZE:
707708
query_params = {"format": "url"}
708709
large_output = True
709710

nextmv/cloud/client.py

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
"""Module with the client class."""
22

3+
import json
34
import os
4-
import sys
55
from dataclasses import dataclass, field
66
from typing import Any
77
from urllib.parse import urljoin
88

99
import requests
1010
from requests.adapters import HTTPAdapter, Retry
1111

12+
_MAX_LAMBDA_PAYLOAD_SIZE: int = 500 * 1024 * 1024
13+
"""Maximum size of the payload handled by the Nextmv Cloud API."""
14+
1215

1316
@dataclass
1417
class Client:
@@ -37,8 +40,6 @@ class Client:
3740
seconds."""
3841
headers: dict[str, str] | None = None
3942
"""Headers to use for requests to the Nextmv Cloud API."""
40-
max_lambda_payload_size: int = 500 * 1024 * 1024
41-
"""Maximum size of the payload handled by the Nextmv Cloud API."""
4243
max_retries: int = 10
4344
"""Maximum number of retries to use for requests to the Nextmv Cloud
4445
API."""
@@ -102,16 +103,16 @@ def request(
102103
if payload is not None and data is not None:
103104
raise ValueError("cannot use both data and payload")
104105

105-
if payload is not None and get_size(payload) > self.max_lambda_payload_size:
106+
if payload is not None and get_size(payload) > _MAX_LAMBDA_PAYLOAD_SIZE:
106107
raise ValueError(
107108
f"payload size of {get_size(payload)} bytes exceeds the maximum "
108-
f"allowed size of {self.max_lambda_payload_size} bytes"
109+
f"allowed size of {_MAX_LAMBDA_PAYLOAD_SIZE} bytes"
109110
)
110111

111-
if data is not None and get_size(data) > self.max_lambda_payload_size:
112+
if data is not None and get_size(data) > _MAX_LAMBDA_PAYLOAD_SIZE:
112113
raise ValueError(
113114
f"data size of {get_size(data)} bytes exceeds the maximum "
114-
f"allowed size of {self.max_lambda_payload_size} bytes"
115+
f"allowed size of {_MAX_LAMBDA_PAYLOAD_SIZE} bytes"
115116
)
116117

117118
session = requests.Session()
@@ -150,24 +151,8 @@ def request(
150151
return response
151152

152153

153-
def get_size(obj: dict | Any, seen: set | Any = None) -> int:
154-
"""Recursively finds size of objects"""
155-
156-
size = sys.getsizeof(obj)
157-
if seen is None:
158-
seen = set()
159-
obj_id = id(obj)
160-
if obj_id in seen:
161-
return 0
162-
163-
# Important mark as seen *before* entering recursion to gracefully handle
164-
# self-referential objects
165-
seen.add(obj_id)
166-
if isinstance(obj, dict):
167-
size += sum([get_size(v, seen) for v in obj.values()])
168-
size += sum([get_size(k, seen) for k in obj.keys()])
169-
elif hasattr(obj, "__dict__"):
170-
size += get_size(obj.__dict__, seen)
171-
elif hasattr(obj, "__iter__") and not isinstance(obj, str | bytes | bytearray):
172-
size += sum([get_size(i, seen) for i in obj])
173-
return size
154+
def get_size(obj: dict[str, Any]) -> int:
155+
"""Finds the size of an object in bytes."""
156+
157+
obj_str = json.dumps(obj, separators=(",", ":"))
158+
return len(obj_str.encode("utf-8"))

0 commit comments

Comments
 (0)