78
78
when sending metadata for ACLs to the API.
79
79
"""
80
80
81
+ from gcloud .storage ._helpers import _require_connection
82
+
81
83
82
84
class _ACLEntity (object ):
83
85
"""Class representing a set of roles for an entity.
@@ -167,8 +169,14 @@ def revoke_owner(self):
167
169
class ACL (object ):
168
170
"""Container class representing a list of access controls."""
169
171
172
+ _URL_PATH_ELEM = 'acl'
170
173
loaded = False
171
174
175
+ # Subclasses must override to provide these attributes (typically,
176
+ # as properties).
177
+ reload_path = None
178
+ save_path = None
179
+
172
180
def __init__ (self ):
173
181
self .entities = {}
174
182
@@ -345,77 +353,33 @@ def get_entities(self):
345
353
self ._ensure_loaded ()
346
354
return list (self .entities .values ())
347
355
348
- def reload (self ):
356
+ def reload (self , connection = None ):
349
357
"""Reload the ACL data from Cloud Storage.
350
358
351
- This is a virtual method, expected to be implemented by subclasses.
352
-
353
- :raises: :class:`NotImplementedError`
354
- """
355
- raise NotImplementedError
356
-
357
- def save (self , acl = None ):
358
- """A method to be overridden by subclasses.
359
-
360
- :type acl: :class:`gcloud.storage.acl.ACL`, or a compatible list.
361
- :param acl: The ACL object to save. If left blank, this will save
362
- current entries.
363
-
364
- :raises: NotImplementedError
365
- """
366
- raise NotImplementedError
367
-
368
- def clear (self ):
369
- """Remove all entities from the ACL."""
370
- raise NotImplementedError
371
-
372
-
373
- class BucketACL (ACL ):
374
- """An ACL specifically for a bucket."""
375
-
376
- _URL_PATH_ELEM = 'acl'
377
-
378
- def __init__ (self , bucket ):
359
+ :type connection: :class:`gcloud.storage.connection.Connection` or None
360
+ :param connection: explicit connection to use for API request;
361
+ defaults to instance property.
379
362
"""
380
- :type bucket: :class:`gcloud.storage.bucket.Bucket`
381
- :param bucket: The bucket to which this ACL relates.
382
- """
383
- super (BucketACL , self ).__init__ ()
384
- self .bucket = bucket
363
+ path = self .reload_path
364
+ connection = _require_connection (connection )
385
365
386
- def reload (self ):
387
- """Reload the ACL data from Cloud Storage."""
388
366
self .entities .clear ()
389
367
390
- url_path = '%s/%s' % (self .bucket .path , self ._URL_PATH_ELEM )
391
- found = self .bucket .connection .api_request (method = 'GET' , path = url_path )
368
+ found = connection .api_request (method = 'GET' , path = path )
392
369
self .loaded = True
393
370
for entry in found .get ('items' , ()):
394
371
self .add_entity (self .entity_from_dict (entry ))
395
372
396
- def save (self , acl = None ):
373
+ def save (self , acl = None , connection = None ):
397
374
"""Save this ACL for the current bucket.
398
375
399
- If called without arguments, this will save the entries
400
- currently stored on this ACL::
401
-
402
- >>> acl.save()
403
-
404
- You can also provide a specific ACL to save instead of the one
405
- currently set on the Bucket object::
406
-
407
- >>> acl.save(acl=my_other_acl)
408
-
409
- You can use this to set access controls to be consistent from
410
- one bucket to another::
411
-
412
- >>> bucket1 = storage.get_bucket(bucket1_name, connection=connection)
413
- >>> bucket2 = storage.get_bucket(bucket2_name, connection=connection)
414
- >>> bucket2.acl.save(bucket1.acl)
415
-
416
376
:type acl: :class:`gcloud.storage.acl.ACL`, or a compatible list.
417
377
:param acl: The ACL object to save. If left blank, this will save
418
378
current entries.
379
+
380
+ :type connection: :class:`gcloud.storage.connection.Connection` or None
381
+ :param connection: explicit connection to use for API request;
382
+ defaults to instance property.
419
383
"""
420
384
if acl is None :
421
385
acl = self
@@ -424,38 +388,53 @@ def save(self, acl=None):
424
388
save_to_backend = True
425
389
426
390
if save_to_backend :
427
- result = self .bucket .connection .api_request (
428
- method = 'PATCH' , path = self .bucket .path ,
391
+ path = self .save_path
392
+ connection = _require_connection (connection )
393
+ result = connection .api_request (
394
+ method = 'PATCH' ,
395
+ path = path ,
429
396
data = {self ._URL_PATH_ELEM : list (acl )},
430
397
query_params = {'projection' : 'full' })
431
398
self .entities .clear ()
432
399
for entry in result .get (self ._URL_PATH_ELEM , ()):
433
400
self .add_entity (self .entity_from_dict (entry ))
434
401
self .loaded = True
435
402
436
- def clear (self ):
403
+ def clear (self , connection = None ):
437
404
"""Remove all ACL entries.
438
405
439
406
Note that this won't actually remove *ALL* the rules, but it
440
407
will remove all the non-default rules. In short, you'll still
441
408
have access to a bucket that you created even after you clear
442
409
ACL rules with this method.
443
410
444
- For example, imagine that you granted access to this bucket to a
445
- bunch of coworkers::
446
-
447
- >>> acl.user('[email protected] ').grant_read()
448
- >>> acl.user('[email protected] ').grant_read()
449
- >>> acl.save()
411
+ :type connection: :class:`gcloud.storage.connection.Connection` or None
412
+ :param connection: explicit connection to use for API request;
413
+ defaults to instance property.
414
+ """
415
+ self .save ([], connection )
450
416
451
- Now they work in another part of the company and you want to
452
- 'start fresh' on who has access::
453
417
454
- >>> acl.clear()
418
+ class BucketACL (ACL ):
419
+ """An ACL specifically for a bucket."""
455
420
456
- At this point all the custom rules you created have been removed.
421
+ def __init__ ( self , bucket ):
457
422
"""
458
- self .save ([])
423
+ :type bucket: :class:`gcloud.storage.bucket.Bucket`
424
+ :param bucket: The bucket to which this ACL relates.
425
+ """
426
+ super (BucketACL , self ).__init__ ()
427
+ self .bucket = bucket
428
+
429
+ @property
430
+ def reload_path (self ):
431
+ """Compute the path for GET API requests for this ACL."""
432
+ return '%s/%s' % (self .bucket .path , self ._URL_PATH_ELEM )
433
+
434
+ @property
435
+ def save_path (self ):
436
+ """Compute the path for PATCH API requests for this ACL."""
437
+ return self .bucket .path
459
438
460
439
461
440
class DefaultObjectACL (BucketACL ):
@@ -475,44 +454,12 @@ def __init__(self, blob):
475
454
super (ObjectACL , self ).__init__ ()
476
455
self .blob = blob
477
456
478
- def reload (self ):
479
- """Reload the ACL data from Cloud Storage."""
480
- self .entities .clear ()
481
-
482
- url_path = '%s/acl' % self .blob .path
483
- found = self .blob .connection .api_request (method = 'GET' , path = url_path )
484
- self .loaded = True
485
- for entry in found .get ('items' , ()):
486
- self .add_entity (self .entity_from_dict (entry ))
487
-
488
- def save (self , acl = None ):
489
- """Save the ACL data for this blob.
457
+ @property
458
+ def reload_path (self ):
459
+ """Compute the path for GET API requests for this ACL."""
460
+ return '%s/acl' % self .blob .path
490
461
491
- :type acl: :class:`gcloud.storage.acl.ACL`
492
- :param acl: The ACL object to save. If left blank, this will
493
- save the entries set locally on the ACL.
494
- """
495
- if acl is None :
496
- acl = self
497
- save_to_backend = acl .loaded
498
- else :
499
- save_to_backend = True
500
-
501
- if save_to_backend :
502
- result = self .blob .connection .api_request (
503
- method = 'PATCH' , path = self .blob .path , data = {'acl' : list (acl )},
504
- query_params = {'projection' : 'full' })
505
- self .entities .clear ()
506
- for entry in result .get ('acl' , ()):
507
- self .add_entity (self .entity_from_dict (entry ))
508
- self .loaded = True
509
-
510
- def clear (self ):
511
- """Remove all ACL rules from the blob.
512
-
513
- Note that this won't actually remove *ALL* the rules, but it
514
- will remove all the non-default rules. In short, you'll still
515
- have access to a blob that you created even after you clear ACL
516
- rules with this method.
517
- """
518
- self .save ([])
462
+ @property
463
+ def save_path (self ):
464
+ """Compute the path for PATCH API requests for this ACL."""
465
+ return self .blob .path
0 commit comments