Skip to content

Commit bbf79af

Browse files
authored
Merge pull request #31 from TaskarCenterAtUW/develop
Develop
2 parents 8f0e4bb + 92e77b8 commit bbf79af

5 files changed

Lines changed: 150 additions & 31 deletions

File tree

freeze_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
build_date = date.today().strftime('%Y-%m-%d')
1313

14-
version = '0.0.18'
14+
version = '0.0.19'
1515

1616
with open(version_file_path, 'w+') as version_file:
1717
version_file.write("version = '{}'\n".format(version))

requirements.txt

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
1-
azure-common==1.1.28
2-
azure-core==1.26.1
3-
azure-servicebus==7.0.0
4-
azure-storage-blob==12.14.1
5-
certifi==2022.12.7
6-
cffi==1.15.1
7-
charset-normalizer==2.1.1
8-
cryptography==39.0.0
9-
idna==3.4
10-
isodate==0.6.1
11-
msrest==0.7.1
12-
oauthlib==3.2.2
13-
pycparser==2.21
14-
python-dotenv==0.21.0
15-
requests==2.28.1
16-
requests-oauthlib==1.3.1
17-
six==1.16.0
18-
typing_extensions==4.4.0
19-
uamqp==1.6.3
20-
urllib3==1.26.14
21-
pika==1.3.1
22-
httpx==0.24.1
23-
coverage==7.2.7
24-
html_testRunner==1.2.1
25-
psutil==5.9.5
1+
azure-common~=1.1.28
2+
azure-core~=1.30.1
3+
azure-servicebus~=7.12.2
4+
azure-storage-blob~=12.20.0
5+
certifi~=2024.2.2
6+
cffi~=1.16.0
7+
charset-normalizer~=3.3.2
8+
cryptography~=39.0.0
9+
idna~=3.7
10+
isodate~=0.6.1
11+
msrest~=0.7.1
12+
oauthlib~=3.2.2
13+
pycparser~=2.22
14+
python-dotenv~=1.0.1
15+
requests~=2.31.0
16+
requests-oauthlib~=2.0.0
17+
six~=1.16.0
18+
typing_extensions~=4.11.0
19+
uamqp~=1.6.9
20+
urllib3~=2.2.1
21+
pika~=1.3.2
22+
httpx~=0.27.0
23+
coverage~=7.5.1
24+
html_testRunner~=1.2.1
25+
psutil~=5.9.8
Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,71 @@
11
from abc import ABC, abstractmethod
22

33

4+
45
class StorageClient(ABC):
6+
"""Abstract base class for a storage client."""
7+
58
@abstractmethod
6-
def get_container(self, name: str): pass
9+
def get_container(self, name: str):
10+
"""Get a container by name.
11+
12+
Args:
13+
name (str): The name of the container.
14+
15+
Returns:
16+
The container object.
17+
"""
18+
pass
19+
20+
@abstractmethod
21+
def get_file(self, container_name: str, file_name: str):
22+
"""Get a file from a container.
23+
24+
Args:
25+
container_name (str): The name of the container.
26+
file_name (str): The name of the file.
27+
28+
Returns:
29+
The file object.
30+
"""
31+
pass
732

833
@abstractmethod
9-
def get_file(self, container_name: str, file_name: str): pass
34+
def get_file_from_url(self, container_name: str, full_url: str):
35+
"""Get a file from a URL.
36+
37+
Args:
38+
container_name (str): The name of the container.
39+
full_url (str): The full URL of the file.
40+
41+
Returns:
42+
The file object.
43+
"""
44+
pass
1045

1146
@abstractmethod
12-
def get_file_from_url(self, container_name: str, full_url: str): pass
47+
def get_sas_url(self, container_name: str, file_path: str, expiry_hours: int) -> str:
48+
"""Get a shared access signature (SAS) URL for a file.
49+
50+
Args:
51+
container_name (str): The name of the container.
52+
file_path (str): The path of the file.
53+
expiry_hours (int): The number of hours until the SAS URL expires.
54+
55+
Returns:
56+
The SAS URL as a string.
57+
"""
58+
pass
59+
# class StorageClient(ABC):
60+
# #
61+
# @abstractmethod
62+
# def get_container(self, name: str): pass
63+
64+
# @abstractmethod
65+
# def get_file(self, container_name: str, file_name: str): pass
66+
67+
# @abstractmethod
68+
# def get_file_from_url(self, container_name: str, full_url: str): pass
1369

70+
# @abstractmethod
71+
# def get_sas_url(self, container_name:str,file_path: str, expiry_hours:int) -> str: pass

src/python_ms_core/core/storage/providers/azure/azure_storage_client.py

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import logging
22
import urllib.parse
3-
from azure.storage.blob import BlobServiceClient
3+
from azure.storage.blob import BlobServiceClient, generate_blob_sas, BlobSasPermissions
44
from . import azure_file_entity, azure_storage_container
55
from ...abstract import storage_client
66
from ....resource_errors import ExceptionHandler
7-
7+
import datetime
88

99
class AzureStorageClient(storage_client.StorageClient):
10+
"""
11+
Represents a client for interacting with Azure Storage.
12+
"""
13+
1014
_blob_service_client: BlobServiceClient
1115

1216
def __init__(self, config):
@@ -16,6 +20,15 @@ def __init__(self, config):
1620

1721
@ExceptionHandler.decorated
1822
def get_container(self, container_name: str):
23+
"""
24+
Retrieves the Azure Storage container with the specified name.
25+
26+
Args:
27+
container_name (str): The name of the container.
28+
29+
Returns:
30+
azure_storage_container.AzureStorageContainer: The Azure Storage container object.
31+
"""
1932
if container_name:
2033
client_container = self._blob_service_client.get_container_client(container_name)
2134
return azure_storage_container.AzureStorageContainer(container_name, client_container)
@@ -25,12 +38,32 @@ def get_container(self, container_name: str):
2538

2639
@ExceptionHandler.decorated
2740
def get_file(self, container_name: str, file_name: str):
41+
"""
42+
Retrieves the Azure Storage file with the specified name from the specified container.
43+
44+
Args:
45+
container_name (str): The name of the container.
46+
file_name (str): The name of the file.
47+
48+
Returns:
49+
azure_file_entity.AzureFileEntity: The Azure Storage file object.
50+
"""
2851
client_container = self._blob_service_client.get_container_client(container_name)
2952
blob_client = client_container.get_blob_client(file_name)
3053
return azure_file_entity.AzureFileEntity(file_name, blob_client)
3154

3255
@ExceptionHandler.decorated
3356
def get_file_from_url(self, container_name: str, full_url: str):
57+
"""
58+
Retrieves the Azure Storage file from the specified URL.
59+
60+
Args:
61+
container_name (str): The name of the container.
62+
full_url (str): The full URL of the file.
63+
64+
Returns:
65+
azure_file_entity.AzureFileEntity: The Azure Storage file object.
66+
"""
3467
path = '/'.join(urllib.parse.unquote(full_url).split('/')[4:])
3568
file = azure_file_entity.AzureFileEntity
3669
client_container = self._blob_service_client.get_container_client(container_name)
@@ -40,3 +73,27 @@ def get_file_from_url(self, container_name: str, full_url: str):
4073
if file_info.file_path == path:
4174
file = file_info
4275
return file
76+
77+
78+
def get_sas_url(self, container_name: str, file_path: str, expiry_hours:int = 12) -> str:
79+
"""
80+
Generates a Shared Access Signature (SAS) URL for the specified Azure Storage file.
81+
82+
Args:
83+
container_name (str): The name of the container.
84+
file_path (str): The path of the file within the container.
85+
expiry_hours (int, optional): The number of hours until the SAS URL expires. Defaults to 12.
86+
87+
Returns:
88+
str: The SAS URL for the file.
89+
"""
90+
sas_token = generate_blob_sas(
91+
self._blob_service_client.account_name,
92+
container_name,
93+
file_path,
94+
account_key=self._blob_service_client.credential.account_key,
95+
permission=BlobSasPermissions(read=True),
96+
expiry=datetime.datetime.utcnow() + datetime.timedelta(hours=expiry_hours)
97+
)
98+
sas_url = f"https://{self._blob_service_client.account_name}.blob.core.windows.net/{container_name}/{file_path}?{sas_token}"
99+
return sas_url

src/python_ms_core/core/storage/providers/local/local_storage_client.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,7 @@ def get_file_from_url(self, container_name: str, full_url: str):
3333
if file_info.path == path:
3434
file = file_info
3535
return file
36+
37+
@ExceptionHandler.decorated
38+
def get_sas_url(self, container_name: str, file_path: str, expiry_hours: int) -> str:
39+
return self.get_file_from_url(container_name, file_path).get_remote_url()

0 commit comments

Comments
 (0)