Skip to content

Commit f74da2f

Browse files
[Blob] Added ContainerClient.exists() method (#16315)
* Added ContainerClient.exists() method * lint
1 parent 25617a6 commit f74da2f

File tree

8 files changed

+292
-7
lines changed

8 files changed

+292
-7
lines changed

sdk/storage/azure-storage-blob/azure/storage/blob/_blob_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,10 +1091,10 @@ def exists(self, **kwargs):
10911091
Returns True if a blob exists with the defined parameters, and returns
10921092
False otherwise.
10931093
1094-
:param str version_id:
1094+
:kwarg str version_id:
10951095
The version id parameter is an opaque DateTime
10961096
value that, when present, specifies the version of the blob to check if it exists.
1097-
:param int timeout:
1097+
:kwarg int timeout:
10981098
The timeout parameter is expressed in seconds.
10991099
:returns: boolean
11001100
"""

sdk/storage/azure-storage-blob/azure/storage/blob/_container_client.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import six
2222

2323
from azure.core import MatchConditions
24-
from azure.core.exceptions import HttpResponseError
24+
from azure.core.exceptions import HttpResponseError, ResourceNotFoundError
2525
from azure.core.paging import ItemPaged
2626
from azure.core.tracing.decorator import distributed_trace
2727
from azure.core.pipeline import Pipeline
@@ -459,6 +459,25 @@ def get_container_properties(self, **kwargs):
459459
response.name = self.container_name
460460
return response # type: ignore
461461

462+
@distributed_trace
463+
def exists(self, **kwargs):
464+
# type: (**Any) -> bool
465+
"""
466+
Returns True if a container exists and returns False otherwise.
467+
468+
:kwarg int timeout:
469+
The timeout parameter is expressed in seconds.
470+
:returns: boolean
471+
"""
472+
try:
473+
self._client.container.get_properties(**kwargs)
474+
return True
475+
except HttpResponseError as error:
476+
try:
477+
process_storage_error(error)
478+
except ResourceNotFoundError:
479+
return False
480+
462481
@distributed_trace
463482
def set_container_metadata( # type: ignore
464483
self, metadata=None, # type: Optional[Dict[str, str]]

sdk/storage/azure-storage-blob/azure/storage/blob/aio/_blob_client_async.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -569,10 +569,10 @@ async def exists(self, **kwargs):
569569
Returns True if a blob exists with the defined parameters, and returns
570570
False otherwise.
571571
572-
:param str version_id:
572+
:kwarg str version_id:
573573
The version id parameter is an opaque DateTime
574574
value that, when present, specifies the version of the blob to check if it exists.
575-
:param int timeout:
575+
:kwarg int timeout:
576576
The timeout parameter is expressed in seconds.
577577
:returns: boolean
578578
"""

sdk/storage/azure-storage-blob/azure/storage/blob/aio/_container_client_async.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
TYPE_CHECKING
1212
)
1313

14-
from azure.core.exceptions import HttpResponseError
14+
from azure.core.exceptions import HttpResponseError, ResourceNotFoundError
1515
from azure.core.tracing.decorator import distributed_trace
1616
from azure.core.tracing.decorator_async import distributed_trace_async
1717
from azure.core.async_paging import AsyncItemPaged
@@ -335,6 +335,25 @@ async def get_container_properties(self, **kwargs):
335335
response.name = self.container_name
336336
return response # type: ignore
337337

338+
@distributed_trace_async
339+
async def exists(self, **kwargs):
340+
# type: (**Any) -> bool
341+
"""
342+
Returns True if a container exists and returns False otherwise.
343+
344+
:kwarg int timeout:
345+
The timeout parameter is expressed in seconds.
346+
:returns: boolean
347+
"""
348+
try:
349+
await self._client.container.get_properties(**kwargs)
350+
return True
351+
except HttpResponseError as error:
352+
try:
353+
process_storage_error(error)
354+
except ResourceNotFoundError:
355+
return False
356+
338357
@distributed_trace_async
339358
async def set_container_metadata( # type: ignore
340359
self, metadata=None, # type: Optional[Dict[str, str]]
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
interactions:
2+
- request:
3+
body: null
4+
headers:
5+
Accept:
6+
- application/xml
7+
Accept-Encoding:
8+
- gzip, deflate
9+
Connection:
10+
- keep-alive
11+
Content-Length:
12+
- '0'
13+
User-Agent:
14+
- azsdk-python-storage-blob/12.7.2 Python/3.8.5 (Windows-10-10.0.19041-SP0)
15+
x-ms-date:
16+
- Sun, 24 Jan 2021 23:07:30 GMT
17+
x-ms-version:
18+
- '2020-04-08'
19+
method: PUT
20+
uri: https://storagename.blob.core.windows.net/container112fe0ef2?restype=container
21+
response:
22+
body:
23+
string: "\uFEFF<?xml version=\"1.0\" encoding=\"utf-8\"?><Error><Code>ContainerAlreadyExists</Code><Message>The
24+
specified container already exists.\nRequestId:34e48888-401e-009f-08a5-f21ff6000000\nTime:2021-01-24T23:07:30.9942715Z</Message></Error>"
25+
headers:
26+
content-length:
27+
- '230'
28+
content-type:
29+
- application/xml
30+
date:
31+
- Sun, 24 Jan 2021 23:07:30 GMT
32+
server:
33+
- Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
34+
x-ms-error-code:
35+
- ContainerAlreadyExists
36+
x-ms-version:
37+
- '2020-04-08'
38+
status:
39+
code: 409
40+
message: The specified container already exists.
41+
- request:
42+
body: null
43+
headers:
44+
Accept:
45+
- application/xml
46+
Accept-Encoding:
47+
- gzip, deflate
48+
Connection:
49+
- keep-alive
50+
User-Agent:
51+
- azsdk-python-storage-blob/12.7.2 Python/3.8.5 (Windows-10-10.0.19041-SP0)
52+
x-ms-date:
53+
- Sun, 24 Jan 2021 23:07:31 GMT
54+
x-ms-version:
55+
- '2020-04-08'
56+
method: GET
57+
uri: https://storagename.blob.core.windows.net/container112fe0ef2?restype=container
58+
response:
59+
body:
60+
string: ''
61+
headers:
62+
content-length:
63+
- '0'
64+
date:
65+
- Sun, 24 Jan 2021 23:07:31 GMT
66+
etag:
67+
- '"0x8D8C0BA190EF0A2"'
68+
last-modified:
69+
- Sun, 24 Jan 2021 22:47:58 GMT
70+
server:
71+
- Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
72+
vary:
73+
- Origin
74+
x-ms-default-encryption-scope:
75+
- $account-encryption-key
76+
x-ms-deny-encryption-scope-override:
77+
- 'false'
78+
x-ms-has-immutability-policy:
79+
- 'false'
80+
x-ms-has-legal-hold:
81+
- 'false'
82+
x-ms-lease-state:
83+
- available
84+
x-ms-lease-status:
85+
- unlocked
86+
x-ms-version:
87+
- '2020-04-08'
88+
status:
89+
code: 200
90+
message: OK
91+
- request:
92+
body: null
93+
headers:
94+
Accept:
95+
- application/xml
96+
Accept-Encoding:
97+
- gzip, deflate
98+
Connection:
99+
- keep-alive
100+
User-Agent:
101+
- azsdk-python-storage-blob/12.7.2 Python/3.8.5 (Windows-10-10.0.19041-SP0)
102+
x-ms-date:
103+
- Sun, 24 Jan 2021 23:07:31 GMT
104+
x-ms-version:
105+
- '2020-04-08'
106+
method: GET
107+
uri: https://storagename.blob.core.windows.net/container212fe0ef2?restype=container
108+
response:
109+
body:
110+
string: "\uFEFF<?xml version=\"1.0\" encoding=\"utf-8\"?><Error><Code>ContainerNotFound</Code><Message>The
111+
specified container does not exist.\nRequestId:34e488e9-401e-009f-63a5-f21ff6000000\nTime:2021-01-24T23:07:31.1273672Z</Message></Error>"
112+
headers:
113+
content-length:
114+
- '225'
115+
content-type:
116+
- application/xml
117+
date:
118+
- Sun, 24 Jan 2021 23:07:31 GMT
119+
server:
120+
- Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
121+
vary:
122+
- Origin
123+
x-ms-error-code:
124+
- ContainerNotFound
125+
x-ms-version:
126+
- '2020-04-08'
127+
status:
128+
code: 404
129+
message: The specified container does not exist.
130+
version: 1
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
interactions:
2+
- request:
3+
body: null
4+
headers:
5+
Accept:
6+
- application/xml
7+
User-Agent:
8+
- azsdk-python-storage-blob/12.7.2 Python/3.8.5 (Windows-10-10.0.19041-SP0)
9+
x-ms-date:
10+
- Sun, 24 Jan 2021 23:08:38 GMT
11+
x-ms-version:
12+
- '2020-04-08'
13+
method: PUT
14+
uri: https://storagename.blob.core.windows.net/container175a3116f?restype=container
15+
response:
16+
body:
17+
string: ''
18+
headers:
19+
content-length: '0'
20+
date: Sun, 24 Jan 2021 23:08:37 GMT
21+
etag: '"0x8D8C0BCFBA744BA"'
22+
last-modified: Sun, 24 Jan 2021 23:08:38 GMT
23+
server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
24+
x-ms-version: '2020-04-08'
25+
status:
26+
code: 201
27+
message: Created
28+
url: https://emilydevtest.blob.core.windows.net/container175a3116f?restype=container
29+
- request:
30+
body: null
31+
headers:
32+
Accept:
33+
- application/xml
34+
User-Agent:
35+
- azsdk-python-storage-blob/12.7.2 Python/3.8.5 (Windows-10-10.0.19041-SP0)
36+
x-ms-date:
37+
- Sun, 24 Jan 2021 23:08:38 GMT
38+
x-ms-version:
39+
- '2020-04-08'
40+
method: GET
41+
uri: https://storagename.blob.core.windows.net/container175a3116f?restype=container
42+
response:
43+
body:
44+
string: ''
45+
headers:
46+
content-length: '0'
47+
date: Sun, 24 Jan 2021 23:08:37 GMT
48+
etag: '"0x8D8C0BCFBA744BA"'
49+
last-modified: Sun, 24 Jan 2021 23:08:38 GMT
50+
server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
51+
vary: Origin
52+
x-ms-default-encryption-scope: $account-encryption-key
53+
x-ms-deny-encryption-scope-override: 'false'
54+
x-ms-has-immutability-policy: 'false'
55+
x-ms-has-legal-hold: 'false'
56+
x-ms-lease-state: available
57+
x-ms-lease-status: unlocked
58+
x-ms-version: '2020-04-08'
59+
status:
60+
code: 200
61+
message: OK
62+
url: https://emilydevtest.blob.core.windows.net/container175a3116f?restype=container
63+
- request:
64+
body: null
65+
headers:
66+
Accept:
67+
- application/xml
68+
User-Agent:
69+
- azsdk-python-storage-blob/12.7.2 Python/3.8.5 (Windows-10-10.0.19041-SP0)
70+
x-ms-date:
71+
- Sun, 24 Jan 2021 23:08:38 GMT
72+
x-ms-version:
73+
- '2020-04-08'
74+
method: GET
75+
uri: https://storagename.blob.core.windows.net/container275a3116f?restype=container
76+
response:
77+
body:
78+
string: "\uFEFF<?xml version=\"1.0\" encoding=\"utf-8\"?><Error><Code>ContainerNotFound</Code><Message>The
79+
specified container does not exist.\nRequestId:f0e7bd23-001e-00b1-54a5-f24de1000000\nTime:2021-01-24T23:08:38.1833494Z</Message></Error>"
80+
headers:
81+
content-length: '225'
82+
content-type: application/xml
83+
date: Sun, 24 Jan 2021 23:08:37 GMT
84+
server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
85+
vary: Origin
86+
x-ms-error-code: ContainerNotFound
87+
x-ms-version: '2020-04-08'
88+
status:
89+
code: 404
90+
message: The specified container does not exist.
91+
url: https://emilydevtest.blob.core.windows.net/container275a3116f?restype=container
92+
version: 1

sdk/storage/azure-storage-blob/tests/test_container.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,17 @@ def test_get_container_metadata_with_lease_id(self, resource_group, location, st
311311
# Assert
312312
self.assertDictEqual(md, metadata)
313313

314+
@GlobalStorageAccountPreparer()
315+
def test_container_exists(self, resource_group, location, storage_account, storage_account_key):
316+
bsc = BlobServiceClient(self.account_url(storage_account, "blob"), storage_account_key)
317+
318+
container1 = self._create_container(bsc, prefix="container1")
319+
container2_name = self._get_container_reference(prefix="container2")
320+
container2 = bsc.get_container_client(container2_name)
321+
322+
self.assertTrue(container1.exists())
323+
self.assertFalse(container2.exists())
324+
314325
@GlobalStorageAccountPreparer()
315326
def test_get_container_properties(self, resource_group, location, storage_account, storage_account_key):
316327
bsc = BlobServiceClient(self.account_url(storage_account, "blob"), storage_account_key)

sdk/storage/azure-storage-blob/tests/test_container_async.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,10 +379,24 @@ async def test_get_container_metadata_with_lease_id(self, resource_group, locati
379379
# Assert
380380
self.assertDictEqual(md, metadata)
381381

382+
@GlobalStorageAccountPreparer()
383+
@AsyncStorageTestCase.await_prepared_test
384+
async def test_container_exists(self, resource_group, location, storage_account, storage_account_key):
385+
bsc = BlobServiceClient(self.account_url(
386+
storage_account, "blob"), storage_account_key, transport=AiohttpTestTransport())
387+
388+
container1 = await self._create_container(bsc, prefix="container1")
389+
container2_name = self._get_container_reference(prefix="container2")
390+
container2 = bsc.get_container_client(container2_name)
391+
392+
self.assertTrue(await container1.exists())
393+
self.assertFalse(await container2.exists())
394+
382395
@GlobalStorageAccountPreparer()
383396
@AsyncStorageTestCase.await_prepared_test
384397
async def test_get_container_properties(self, resource_group, location, storage_account, storage_account_key):
385-
bsc = BlobServiceClient(self.account_url(storage_account, "blob"), storage_account_key, transport=AiohttpTestTransport())
398+
bsc = BlobServiceClient(
399+
self.account_url(storage_account, "blob"), storage_account_key, transport=AiohttpTestTransport())
386400
metadata = {'hello': 'world', 'number': '42'}
387401
container = await self._create_container(bsc)
388402
await container.set_container_metadata(metadata)

0 commit comments

Comments
 (0)