Skip to content

Commit a536090

Browse files
committed
dl_stream and email try
1 parent 067a0ef commit a536090

File tree

4 files changed

+81
-3
lines changed

4 files changed

+81
-3
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "dean_utils"
7-
version="0.0.17"
7+
version="0.0.18"
88
authors=[
99
{ name="Dean MacGregor", email="powertrading121@gmail.com"}
1010
]

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ adlfs
55
fsspec
66
azure-storage-queue
77
python-multipart
8-
azure-communication-email
8+
azure-communication-email
9+
httpx

src/dean_utils/utils/az_utils.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,18 @@
44
from azure.storage.queue.aio import QueueServiceClient as QSC
55
from azure.storage.queue import TextBase64EncodePolicy
66
import azure.storage.blob as asb
7+
from azure.storage.blob.aio import BlobClient
8+
from azure.storage.blob import BlobBlock
9+
from azure.core.exceptions import HttpResponseError
710
import asyncio
811
from typing import List, Optional
912
import fsspec
13+
import httpx
1014
from datetime import datetime, timedelta, timezone
15+
from typing import TypeAlias, Literal
16+
from uuid import uuid4
17+
18+
HTTPX_METHODS: TypeAlias = Literal["GET", "POST"]
1119

1220

1321
def def_cos(db_name, client_name):
@@ -69,6 +77,66 @@ def __init__(self, connection_string=os.environ["Synblob"]):
6977
}
7078
self.stor = stor
7179

80+
async def stream_dl(
81+
self,
82+
client: httpx.AsyncClient,
83+
method: HTTPX_METHODS,
84+
url: str,
85+
path: str,
86+
/,
87+
recurs=False,
88+
**httpx_extras,
89+
) -> None:
90+
"""
91+
Help on method stream_dl
92+
93+
async stream_dl(client, method, url, **httpx_extras)
94+
Download file streaming in chunks in async as downloader and to a Blob
95+
96+
Parameters
97+
----------
98+
client: httpx.AsyncClient
99+
The httpx Async Client object to use
100+
method:
101+
The HTTP method whether GET or POST
102+
url:
103+
The URL to download
104+
path:
105+
The full path to Azure file being saved
106+
**httpx_extras
107+
Any extra arguments to be sent to client.stream
108+
"""
109+
async with BlobClient.from_connection_string(
110+
self.connection_string, *(path.split("/", maxsplit=1))
111+
) as target, client.stream(method, url, **httpx_extras) as resp:
112+
resp.raise_for_status()
113+
block_list = []
114+
async for chunk in resp.aiter_bytes():
115+
block_id = uuid4().hex
116+
try:
117+
await target.stage_block(block_id=block_id, data=chunk)
118+
except HttpResponseError as err:
119+
if "The specified blob or block content is invalid." not in str(
120+
err
121+
):
122+
raise err
123+
await asyncio.sleep(1)
124+
await target.commit_block_list([])
125+
await target.delete_blob()
126+
if recurs is False:
127+
await self.stream_dl(
128+
client,
129+
method,
130+
url,
131+
path,
132+
recurs=True,
133+
httpx_extras=httpx_extras,
134+
)
135+
else:
136+
raise err
137+
block_list.append(BlobBlock(block_id=block_id))
138+
await target.commit_block_list(block_list)
139+
72140
async def exists(self, path: str):
73141
"""
74142
Help on method _exists in module adlfs.spec:

src/dean_utils/utils/email_utility.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
from azure.communication.email import EmailClient
88

99

10+
class MissingEnvVars(Exception):
11+
pass
12+
13+
1014
def send_email(from_email: str, to_email: str, subject: str, msg: str) -> None:
1115
"""
1216
# Send email using smtp.gmail.com, password must be stored in env variable gmail_pw
@@ -43,7 +47,10 @@ def send_email(from_email: str, to_email: str, subject: str, msg: str) -> None:
4347
server.sendmail(from_email, to_email, mimemsg.as_string())
4448

4549

46-
email_client = EmailClient.from_connection_string(os.environ["azuremail"])
50+
try:
51+
email_client = EmailClient.from_connection_string(os.environ["azuremail"])
52+
except: # noqa: E722
53+
email_client = None
4754

4855

4956
def az_send(
@@ -53,6 +60,8 @@ def az_send(
5360
from_email: str = None,
5461
to_email: str = None,
5562
) -> None:
63+
if email_client is None:
64+
raise MissingEnvVars("missing azuremail var")
5665
if os.environ["error_email"] is not None and to_email is None:
5766
to_email = os.environ["error_email"]
5867
if os.environ["from_email"] is not None and from_email is None:

0 commit comments

Comments
 (0)