@@ -2215,50 +2215,84 @@ class ABSStore(MutableMapping):
2215
2215
----------
2216
2216
container : string
2217
2217
The name of the ABS container to use.
2218
+ .. deprecated::
2219
+ Use ``client`` instead.
2218
2220
prefix : string
2219
2221
Location of the "directory" to use as the root of the storage hierarchy
2220
2222
within the container.
2221
2223
account_name : string
2222
2224
The Azure blob storage account name.
2225
+ .. deprecated:: 2.8.3
2226
+ Use ``client`` instead.
2223
2227
account_key : string
2224
2228
The Azure blob storage account access key.
2229
+ .. deprecated:: 2.8.3
2230
+ Use ``client`` instead.
2225
2231
blob_service_kwargs : dictionary
2226
2232
Extra arguments to be passed into the azure blob client, for e.g. when
2227
2233
using the emulator, pass in blob_service_kwargs={'is_emulated': True}.
2234
+ .. deprecated:: 2.8.3
2235
+ Use ``client`` instead.
2228
2236
dimension_separator : {'.', '/'}, optional
2229
2237
Separator placed between the dimensions of a chunk.
2238
+ client : azure.storage.blob.ContainerClient, optional
2239
+ And ``azure.storage.blob.ContainerClient`` to connect with. See
2240
+ `here <https://docs.microsoft.com/en-us/python/api/azure-storage-blob/azure.storage.blob.containerclient?view=azure-python>`_ # noqa
2241
+ for more.
2242
+
2243
+ .. versionadded:: 2.8.3
2230
2244
2231
2245
Notes
2232
2246
-----
2233
- In order to use this store, you must install the Microsoft Azure Storage SDK for Python.
2247
+ In order to use this store, you must install the Microsoft Azure Storage SDK for Python,
2248
+ ``azure-storage-blob>=12.5.0``.
2234
2249
"""
2235
2250
2236
- def __init__ (self , container , prefix = '' , account_name = None , account_key = None ,
2237
- blob_service_kwargs = None , dimension_separator = None ):
2238
- from azure .storage .blob import BlockBlobService
2239
- self .container = container
2240
- self .prefix = normalize_storage_path (prefix )
2241
- self .account_name = account_name
2242
- self .account_key = account_key
2251
+ def __init__ (self , container = None , prefix = '' , account_name = None , account_key = None ,
2252
+ blob_service_kwargs = None , dimension_separator = None ,
2253
+ client = None ,
2254
+ ):
2243
2255
self ._dimension_separator = dimension_separator
2244
- if blob_service_kwargs is not None :
2245
- self .blob_service_kwargs = blob_service_kwargs
2246
- else : # pragma: no cover
2247
- self .blob_service_kwargs = dict ()
2248
- self .client = BlockBlobService (self .account_name , self .account_key ,
2249
- ** self .blob_service_kwargs )
2250
-
2251
- # needed for pickling
2252
- def __getstate__ (self ):
2253
- state = self .__dict__ .copy ()
2254
- del state ['client' ]
2255
- return state
2256
+ self .prefix = normalize_storage_path (prefix )
2257
+ if client is None :
2258
+ # deprecated option, try to construct the client for them
2259
+ msg = (
2260
+ "Providing 'container', 'account_name', 'account_key', and 'blob_service_kwargs'"
2261
+ "is deprecated. Provide and instance of 'azure.storage.blob.ContainerClient' "
2262
+ "'client' instead."
2263
+ )
2264
+ warnings .warn (msg , FutureWarning , stacklevel = 2 )
2265
+ from azure .storage .blob import ContainerClient
2266
+ blob_service_kwargs = blob_service_kwargs or {}
2267
+ client = ContainerClient (
2268
+ "https://{}.blob.core.windows.net/" .format (account_name ), container ,
2269
+ credential = account_key , ** blob_service_kwargs
2270
+ )
2256
2271
2257
- def __setstate__ (self , state ):
2258
- from azure .storage .blob import BlockBlobService
2259
- self .__dict__ .update (state )
2260
- self .client = BlockBlobService (self .account_name , self .account_key ,
2261
- ** self .blob_service_kwargs )
2272
+ self .client = client
2273
+ self ._container = container
2274
+ self ._account_name = account_name
2275
+ self ._account_key = account_key
2276
+
2277
+ def _warn_deprecated (self , property_ ):
2278
+ msg = ("The {} property is deprecated and will be removed in a future "
2279
+ "version. Get the property from 'ABSStore.client' instead." )
2280
+ warnings .warn (msg .format (property_ ), FutureWarning , stacklevel = 3 )
2281
+
2282
+ @property
2283
+ def container (self ):
2284
+ self ._warn_deprecated ("container" )
2285
+ return self ._container
2286
+
2287
+ @property
2288
+ def account_name (self ):
2289
+ self ._warn_deprecated ("account_name" )
2290
+ return self ._account_name
2291
+
2292
+ @property
2293
+ def account_key (self ):
2294
+ self ._warn_deprecated ("account_key" )
2295
+ return self ._account_key
2262
2296
2263
2297
def _append_path_to_prefix (self , path ):
2264
2298
if self .prefix == '' :
@@ -2277,30 +2311,29 @@ def _strip_prefix_from_path(path, prefix):
2277
2311
return path_norm
2278
2312
2279
2313
def __getitem__ (self , key ):
2280
- from azure .common import AzureMissingResourceHttpError
2314
+ from azure .core . exceptions import ResourceNotFoundError
2281
2315
blob_name = self ._append_path_to_prefix (key )
2282
2316
try :
2283
- blob = self .client .get_blob_to_bytes (self .container , blob_name )
2284
- return blob .content
2285
- except AzureMissingResourceHttpError :
2317
+ return self .client .download_blob (blob_name ).readall ()
2318
+ except ResourceNotFoundError :
2286
2319
raise KeyError ('Blob %s not found' % blob_name )
2287
2320
2288
2321
def __setitem__ (self , key , value ):
2289
2322
value = ensure_bytes (value )
2290
2323
blob_name = self ._append_path_to_prefix (key )
2291
- self .client .create_blob_from_bytes ( self . container , blob_name , value )
2324
+ self .client .upload_blob ( blob_name , value , overwrite = True )
2292
2325
2293
2326
def __delitem__ (self , key ):
2294
- from azure .common import AzureMissingResourceHttpError
2327
+ from azure .core . exceptions import ResourceNotFoundError
2295
2328
try :
2296
- self .client .delete_blob (self .container , self . _append_path_to_prefix (key ))
2297
- except AzureMissingResourceHttpError :
2329
+ self .client .delete_blob (self ._append_path_to_prefix (key ))
2330
+ except ResourceNotFoundError :
2298
2331
raise KeyError ('Blob %s not found' % key )
2299
2332
2300
2333
def __eq__ (self , other ):
2301
2334
return (
2302
2335
isinstance (other , ABSStore ) and
2303
- self .container == other .container and
2336
+ self .client == other .client and
2304
2337
self .prefix == other .prefix
2305
2338
)
2306
2339
@@ -2312,63 +2345,53 @@ def __iter__(self):
2312
2345
list_blobs_prefix = self .prefix + '/'
2313
2346
else :
2314
2347
list_blobs_prefix = None
2315
- for blob in self .client .list_blobs (self . container , list_blobs_prefix ):
2348
+ for blob in self .client .list_blobs (list_blobs_prefix ):
2316
2349
yield self ._strip_prefix_from_path (blob .name , self .prefix )
2317
2350
2318
2351
def __len__ (self ):
2319
2352
return len (self .keys ())
2320
2353
2321
2354
def __contains__ (self , key ):
2322
2355
blob_name = self ._append_path_to_prefix (key )
2323
- assert len (blob_name ) >= 1
2324
- if self .client .exists (self .container , blob_name ):
2325
- return True
2326
- else :
2327
- return False
2356
+ return self .client .get_blob_client (blob_name ).exists ()
2328
2357
2329
2358
def listdir (self , path = None ):
2330
- from azure .storage .blob import Blob
2331
2359
dir_path = normalize_storage_path (self ._append_path_to_prefix (path ))
2332
2360
if dir_path :
2333
2361
dir_path += '/'
2334
- items = list ()
2335
- for blob in self .client .list_blobs (self .container , prefix = dir_path , delimiter = '/' ):
2336
- if type (blob ) == Blob :
2337
- items .append (self ._strip_prefix_from_path (blob .name , dir_path ))
2338
- else :
2339
- items .append (self ._strip_prefix_from_path (
2340
- blob .name [:blob .name .find ('/' , len (dir_path ))], dir_path ))
2362
+ items = [
2363
+ self ._strip_prefix_from_path (blob .name , dir_path )
2364
+ for blob in self .client .walk_blobs (name_starts_with = dir_path , delimiter = '/' )
2365
+ ]
2341
2366
return items
2342
2367
2343
2368
def rmdir (self , path = None ):
2344
2369
dir_path = normalize_storage_path (self ._append_path_to_prefix (path ))
2345
2370
if dir_path :
2346
2371
dir_path += '/'
2347
- for blob in self .client .list_blobs (self .container , prefix = dir_path ):
2348
- assert len (blob .name ) >= 1
2349
- self .client .delete_blob (self .container , blob .name )
2372
+ for blob in self .client .list_blobs (name_starts_with = dir_path ):
2373
+ self .client .delete_blob (blob )
2350
2374
2351
2375
def getsize (self , path = None ):
2352
- from azure .storage .blob import Blob
2353
2376
store_path = normalize_storage_path (path )
2354
- fs_path = self .prefix
2355
- if store_path :
2356
- fs_path = self ._append_path_to_prefix (store_path )
2377
+ fs_path = self ._append_path_to_prefix (store_path )
2378
+ if fs_path :
2379
+ blob_client = self .client .get_blob_client (fs_path )
2380
+ else :
2381
+ blob_client = None
2357
2382
2358
- if fs_path != "" and self .client .exists (self .container , fs_path ):
2359
- return self .client .get_blob_properties (
2360
- self .container , fs_path
2361
- ).properties .content_length
2383
+ if blob_client and blob_client .exists ():
2384
+ return blob_client .get_blob_properties ().size
2362
2385
else :
2363
2386
size = 0
2364
2387
if fs_path == '' :
2365
2388
fs_path = None
2366
- else :
2389
+ elif not fs_path . endswith ( '/' ) :
2367
2390
fs_path += '/'
2368
- for blob in self .client .list_blobs ( self . container , prefix = fs_path ,
2369
- delimiter = '/' ):
2370
- if type ( blob ) == Blob :
2371
- size += blob . properties . content_length
2391
+ for blob in self .client .walk_blobs ( name_starts_with = fs_path , delimiter = '/' ):
2392
+ blob_client = self . client . get_blob_client ( blob )
2393
+ if blob_client . exists () :
2394
+ size += blob_client . get_blob_properties (). size
2372
2395
return size
2373
2396
2374
2397
def clear (self ):
0 commit comments