brynq-sdk-azure 1.0.1__tar.gz → 1.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: brynq_sdk_azure
3
- Version: 1.0.1
3
+ Version: 1.1.1
4
4
  Summary: Azure wrapper from BrynQ
5
5
  Home-page: UNKNOWN
6
6
  Author: BrynQ
@@ -0,0 +1,175 @@
1
+ from brynq_sdk.brynq import BrynQ
2
+ from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient, generate_account_sas, ResourceTypes, AccountSasPermissions
3
+ from typing import Union, List, Tuple
4
+ from datetime import datetime, timedelta
5
+
6
+
7
+ class BlobStorage(BrynQ):
8
+ def __init__(self, label: Union[str, List]):
9
+ super().__init__()
10
+ self.blob_service_client = self.__get_authentication(label=label)
11
+
12
+ def __get_authentication(self, label):
13
+ credentials = self.get_system_credential(system='azure-blob-storage', label=label)
14
+ storage_account_name = credentials['storage_account_name']
15
+ storage_account_key = credentials['storage_account_key']
16
+ sas_token = generate_account_sas(
17
+ account_name=storage_account_name,
18
+ account_key=storage_account_key,
19
+ resource_types=ResourceTypes(service=True, container=True, object=True),
20
+ permission=AccountSasPermissions(read=True, write=True, list=True, delete=True, add=True, create=True, update=True, process=True),
21
+ expiry=datetime.utcnow() + timedelta(hours=1)
22
+ )
23
+ blob_service_client = BlobServiceClient(
24
+ account_url=f"https://{storage_account_name}.blob.core.windows.net",
25
+ credential=sas_token
26
+ )
27
+
28
+ return blob_service_client
29
+
30
+ def get_containers(self):
31
+ all_containers = self.blob_service_client.list_containers(include_metadata=True)
32
+ container_list = []
33
+ for container in all_containers:
34
+ container_info = {
35
+ 'name': container.name,
36
+ 'last_modified': container.last_modified,
37
+ 'etag': container.etag,
38
+ 'lease_state': container.lease,
39
+ 'has_immutability_policy': container.has_immutability_policy,
40
+ 'has_legal_hold': container.has_legal_hold,
41
+ 'metadata': container.metadata
42
+ }
43
+ container_list.append(container_info)
44
+
45
+ return container_list
46
+
47
+ def get_container(self, container_name: str):
48
+ """
49
+ Get a container from the blob storage
50
+ """
51
+ container = self.blob_service_client.get_container_client(container_name)
52
+ return container
53
+
54
+ def create_container(self, container_name: str):
55
+ """
56
+ Create a container in the blob storage
57
+ """
58
+ response = self.blob_service_client.create_container(container_name)
59
+ return response
60
+
61
+ def update_container(self):
62
+ pass
63
+
64
+ def delete_container(self):
65
+ pass
66
+
67
+ def get_folders(self, container_name: str):
68
+ """
69
+ Retrieves a list of 'folders' in the specified container.
70
+ Since Azure Blob Storage uses a flat namespace, folders are simulated using prefixes.
71
+
72
+ :param container_name: The name of the container.
73
+ :return: A list of folder names.
74
+ """
75
+ container_client = self.get_container(container_name)
76
+ blobs_list = container_client.list_blobs()
77
+
78
+ folder_set = set()
79
+ for blob in blobs_list:
80
+ if '/' in blob.name:
81
+ folder = blob.name.split('/')[0]
82
+ folder_set.add(folder)
83
+ folders = list(folder_set)
84
+ return folders
85
+
86
+ def create_folder(self, container_name: str, folder_name: str):
87
+ """
88
+ Create a file with a 0 as content. Because the file is created, the folder is also created. After that the file and the folder are created,
89
+ delete the file so the folder will stay. According to the azure docs, it should be possible to create empty files, but this is not working.
90
+ """
91
+ # Split the url and add the container and folder name in between the url
92
+ original_url = self.blob_service_client.url.split('?')
93
+ url = f"{original_url[0]}/{container_name}/{folder_name}/empty_file?{original_url[1]}"
94
+ blob = BlobClient.from_blob_url(blob_url=url)
95
+
96
+ # Now create the file and delete it so the folder will stay
97
+ response = blob.upload_blob(b"0", blob_type='AppendBlob')
98
+ blob.delete_blob()
99
+ return response
100
+
101
+ def delete_folder(self, container_name: str, folder_name: str):
102
+ """
103
+ Deletes all the blobs (files) within a folder, effectively deleting the folder.
104
+ :param container_name: The name of the container.
105
+ :param folder_name: The name of the folder to delete.
106
+ """
107
+ container_client = self.get_container(container_name)
108
+ blobs = container_client.list_blobs(name_starts_with=f"{folder_name}/")
109
+ for blob in blobs:
110
+ blob_client = container_client.get_blob_client(blob)
111
+ blob_client.delete_blob()
112
+ return f"Deleted folder {folder_name} and all its contents."
113
+
114
+ def get_files(self, container_name: str, folder_name: str = ""):
115
+ """
116
+ Retrieves all files in a container, optionally filtered by folder.
117
+ :param container_name: The name of the container.
118
+ :param folder_name: The name of the folder (optional). If provided, only files in this folder will be listed.
119
+ :return: A list of file names in the container or folder.
120
+ """
121
+ container_client = self.get_container(container_name)
122
+ blobs_list = container_client.list_blobs(name_starts_with=f"{folder_name}/" if folder_name else "")
123
+
124
+ file_list = []
125
+ for blob in blobs_list:
126
+ if not blob.name.endswith('/'): # Exclude folder markers
127
+ file_list.append(blob.name)
128
+
129
+ return file_list
130
+
131
+ def upload_file(self, container_name: str, blob_name: str, file_path: str, overwrite: bool = False):
132
+ """
133
+ Uploads a single file to Azure Blob Storage.
134
+ :param container_name: The name of the container to upload to.
135
+ :param blob_name: The name of the blob (the file name in blob storage).
136
+ :param file_path: The local path to the file to upload.
137
+ :param overwrite: Whether to overwrite an existing blob. Default is False.
138
+ """
139
+ # Get the container client
140
+ container_client = self.get_container(container_name)
141
+
142
+ # Get the blob client
143
+ blob_client = container_client.get_blob_client(blob_name)
144
+
145
+ # Open the file and upload
146
+ with open(file_path, "rb") as data:
147
+ blob_client.upload_blob(data, overwrite=overwrite)
148
+
149
+ print(f"Successfully uploaded {file_path} to {blob_client.url}")
150
+ return blob_client.url
151
+
152
+ def upload_files(self, container_name: str, files: List[Tuple[str, str]], overwrite: bool = False):
153
+ """
154
+ Uploads multiple files to Azure Blob Storage.
155
+ :param container_name: The name of the container to upload to.
156
+ :param files: A list of tuples (blob_name, file_path), where blob_name is the name of the blob in storage, and file_path is the local file path.
157
+ :param overwrite: Whether to overwrite existing blobs. Default is False.
158
+ """
159
+ success = True
160
+ for blob_name, file_path in files:
161
+ result = self.upload_file(container_name, blob_name, file_path, overwrite=overwrite)
162
+ if result is None:
163
+ success = False
164
+ return success
165
+
166
+ def delete_file(self, container_name: str, blob_name: str):
167
+ """
168
+ Deletes a specific file from Azure Blob Storage.
169
+ :param container_name: The name of the container.
170
+ :param blob_name: The name of the blob (the file) to delete.
171
+ """
172
+ container_client = self.get_container(container_name)
173
+ blob_client = container_client.get_blob_client(blob_name)
174
+ blob_client.delete_blob()
175
+ return f"Deleted file {blob_name} from container {container_name}."
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: brynq-sdk-azure
3
- Version: 1.0.1
3
+ Version: 1.1.1
4
4
  Summary: Azure wrapper from BrynQ
5
5
  Home-page: UNKNOWN
6
6
  Author: BrynQ
@@ -2,7 +2,7 @@ from setuptools import setup
2
2
 
3
3
  setup(
4
4
  name='brynq_sdk_azure',
5
- version='1.0.1',
5
+ version='1.1.1',
6
6
  description='Azure wrapper from BrynQ',
7
7
  long_description='Azure wrapper from BrynQ',
8
8
  author='BrynQ',
@@ -1,95 +0,0 @@
1
- from brynq_sdk.brynq import BrynQ
2
- from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient, generate_account_sas, ResourceTypes, AccountSasPermissions
3
- from typing import Union, List
4
- from datetime import datetime, timedelta
5
-
6
-
7
- class BlobStorage(BrynQ):
8
- def __init__(self, label: Union[str, List]):
9
- super().__init__()
10
- self.blob_service_client = self.__get_authentication(label=label)
11
-
12
- def __get_authentication(self, label):
13
- credentials = self.get_system_credential(system='azure-blob-storage', label=label)
14
- storage_account_name = credentials['storage_account_name']
15
- storage_account_key = credentials['storage_account_key']
16
- sas_token = generate_account_sas(
17
- account_name=storage_account_name,
18
- account_key=storage_account_key,
19
- resource_types=ResourceTypes(service=True, container=True, object=True),
20
- permission=AccountSasPermissions(read=True, write=True, list=True, delete=True, add=True, create=True, update=True, process=True),
21
- expiry=datetime.utcnow() + timedelta(hours=1)
22
- )
23
- blob_service_client = BlobServiceClient(
24
- account_url=f"https://{storage_account_name}.blob.core.windows.net",
25
- credential=sas_token
26
- )
27
-
28
- return blob_service_client
29
-
30
- def get_containers(self):
31
- all_containers = self.blob_service_client.list_containers(include_metadata=True)
32
- container_list = []
33
- for container in all_containers:
34
- container_info = {
35
- 'name': container.name,
36
- 'last_modified': container.last_modified,
37
- 'etag': container.etag,
38
- 'lease_state': container.lease,
39
- 'has_immutability_policy': container.has_immutability_policy,
40
- 'has_legal_hold': container.has_legal_hold,
41
- 'metadata': container.metadata
42
- }
43
- container_list.append(container_info)
44
-
45
- return container_list
46
-
47
- def get_container(self, container_name: str):
48
- """
49
- Get a container from the blob storage
50
- """
51
- container = self.blob_service_client.get_container_client(container_name)
52
- return container
53
-
54
- def create_container(self, container_name: str):
55
- """
56
- Create a container in the blob storage
57
- """
58
- response = self.blob_service_client.create_container(container_name)
59
- return response
60
-
61
- def update_container(self):
62
- pass
63
-
64
- def delete_container(self):
65
- pass
66
-
67
- def get_blobs(self):
68
- pass
69
-
70
- def create_blob(self):
71
- pass
72
-
73
- def delete_blob(self):
74
- pass
75
-
76
- def get_folders(self):
77
- pass
78
-
79
- def create_folder(self, container_name: str, folder_name: str):
80
- """
81
- Create a file with a 0 as content. Because the file is created, the folder is also created. After that the file and the folder are created,
82
- delete the file so the folder will stay. According to the azure docs, it should be possible to create empty files, but this is not working.
83
- """
84
- # Split the url and add the container and folder name in between the url
85
- original_url = self.blob_service_client.url.split('?')
86
- url = f"{original_url[0]}/{container_name}/{folder_name}/empty_file?{original_url[1]}"
87
- blob = BlobClient.from_blob_url(blob_url=url)
88
-
89
- # Now create the file and delete it so the folder will stay
90
- response = blob.upload_blob(b"0", blob_type='AppendBlob')
91
- blob.delete_blob()
92
- return response
93
-
94
- def delete_folder(self):
95
- pass