Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement SendEmailBlock #137

Merged
merged 3 commits into from
Mar 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ typer = "^0.9.0"
types-toml = "^0.10.8.7"
apscheduler = "^3.10.4"
httpx = "^0.27.0"
filetype = "^1.2.0"


[tool.poetry.group.dev.dependencies]
Expand Down
6 changes: 6 additions & 0 deletions skyvern/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,9 @@ def __init__(self, error_message: str) -> None:
class WorkflowRunContextNotInitialized(SkyvernException):
def __init__(self, workflow_run_id: str) -> None:
super().__init__(f"WorkflowRunContext not initialized for workflow run {workflow_run_id}")


class DownloadFileMaxSizeExceeded(SkyvernException):
def __init__(self, max_size: int) -> None:
self.max_size = max_size
super().__init__(f"Download file size exceeded the maximum allowed size of {max_size} MB.")
61 changes: 39 additions & 22 deletions skyvern/forge/sdk/api/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,54 @@
import zipfile
from urllib.parse import urlparse

import requests
import aiohttp
import structlog

from skyvern.exceptions import DownloadFileMaxSizeExceeded

LOG = structlog.get_logger()


def download_file(url: str) -> str | None:
# Send an HTTP request to the URL of the file, stream=True to prevent loading the content at once into memory
r = requests.get(url, stream=True)
async def download_file(url: str, max_size_mb: int | None = None) -> str:
try:
async with aiohttp.ClientSession(raise_for_status=True) as session:
LOG.info("Starting to download file")
async with session.get(url) as response:
# Check the content length if available
if max_size_mb and response.content_length and response.content_length > max_size_mb * 1024 * 1024:
# todo: move to root exception.py
raise DownloadFileMaxSizeExceeded(max_size_mb)

# Parse the URL
a = urlparse(url)

# Check if the request is successful
if r.status_code == 200:
# Parse the URL
a = urlparse(url)
# Get the file name
temp_dir = tempfile.mkdtemp(prefix="skyvern_downloads_")

# Get the file name
temp_dir = tempfile.mkdtemp(prefix="skyvern_downloads_")
file_name = os.path.basename(a.path)
file_path = os.path.join(temp_dir, file_name)

file_name = os.path.basename(a.path)
file_path = os.path.join(temp_dir, file_name)
LOG.info(f"Downloading file to {file_path}")
with open(file_path, "wb") as f:
# Write the content of the request into the file
total_bytes_downloaded = 0
async for chunk in response.content.iter_chunked(1024):
f.write(chunk)
total_bytes_downloaded += len(chunk)
if max_size_mb and total_bytes_downloaded > max_size_mb * 1024 * 1024:
raise DownloadFileMaxSizeExceeded(max_size_mb)

LOG.info(f"Downloading file to {file_path}")
with open(file_path, "wb") as f:
# Write the content of the request into the file
for chunk in r.iter_content(1024):
f.write(chunk)
LOG.info(f"File downloaded successfully to {file_path}")
return file_path
else:
LOG.error(f"Failed to download file, status code: {r.status_code}")
return None
LOG.info(f"File downloaded successfully to {file_path}")
return file_path
except aiohttp.ClientResponseError as e:
LOG.error(f"Failed to download file, status code: {e.status}")
raise
except DownloadFileMaxSizeExceeded as e:
LOG.error(f"Failed to download file, max size exceeded: {e.max_size}")
raise
except Exception:
LOG.exception("Failed to download file")
raise


def zip_files(files_path: str, zip_file_path: str) -> str:
Expand Down
6 changes: 3 additions & 3 deletions skyvern/forge/sdk/workflow/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ def __init__(self, duplicate_keys: set[str]) -> None:
)


class DownloadFileMaxSizeExceeded(BaseWorkflowException):
def __init__(self, max_size: int) -> None:
super().__init__(f"Download file size exceeded the maximum allowed size of {max_size} MB.")
class InvalidEmailClientConfiguration(BaseWorkflowException):
def __init__(self, problems: list[str]) -> None:
super().__init__(f"Email client configuration is invalid. These parameters are missing or invalid: {problems}")
Loading
Loading