Buckets¶
Create and delete a bucket, list the buckets of your account, and turn versioning on and off. The bucket methods work on a bucket path, S3Path("my-bucket").
Setup¶
This cell only prepares the notebook: it connects to AWS with the profile that the s3pathlib CI uses. The demos create and delete a temporary bucket; if a failed run left it behind, the cell deletes it first, so every run starts from the same state.
[1]:
import os
import boto3
from s3pathlib.api import S3Path
from s3pathlib.api import s3_context
boto_ses = boto3.Session(profile_name=os.environ["S3PATHLIB_TEST_AWS_PROFILE"])
s3_context.attach_s3_client(boto_ses.client("s3")) # <-- in your code
aws_account_id = boto_ses.client("sts").get_caller_identity()["Account"]
# a bucket name is global: put your account id in it to make it unique
bucket_name = f"s3pathlib-test-tmp-docs-{aws_account_id}"
if S3Path(bucket_name).exists(): # left over from a failed run
S3Path(bucket_name).delete(is_hard_delete=True, skip_prompt=True)
S3Path(bucket_name).delete_bucket()
print(bucket_name)
s3pathlib-test-tmp-docs-123456789012
1. Create a bucket¶
from_bucket builds a bucket path from a name (the same as S3Path(bucket_name), but it only accepts a bucket name):
[2]:
s3bucket = S3Path.from_bucket(bucket_name)
s3bucket
[2]:
S3Path('s3://s3pathlib-test-tmp-docs-123456789012/')
[3]:
s3bucket.exists()
[3]:
False
create_bucket creates it, in the region of the S3 client unless you pass region. It returns the raw boto3 response:
[4]:
response = s3bucket.create_bucket()
s3bucket.exists()
[4]:
True
In us-east-1, creating a bucket you already own succeeds again (a legacy behavior of S3); in the other regions it raises BucketAlreadyOwnedByYou. A name owned by another AWS account raises BucketAlreadyExists.
2. List buckets¶
list_buckets returns every bucket of the account, as bucket paths:
[5]:
buckets = S3Path.list_buckets()
s3bucket in buckets
[5]:
True
Each bucket path carries what S3 returned: last_modified_at is the creation date of the bucket, and the region is in response["BucketRegion"]:
[6]:
for bucket in buckets:
if bucket == s3bucket:
print(bucket.response["BucketRegion"])
us-east-1
3. Versioning¶
A new bucket has no versioning:
[7]:
s3bucket.is_versioning_enabled()
[7]:
False
put_bucket_versioning(True) enables it:
[8]:
response = s3bucket.put_bucket_versioning(True)
s3bucket.is_versioning_enabled()
[8]:
True
get_bucket_versioning returns the raw response:
[9]:
response = s3bucket.get_bucket_versioning()
response["Status"]
[9]:
'Enabled'
Versioning can never be turned off again, only suspended: new writes no longer add versions, but the existing versions are kept.
[10]:
response = s3bucket.put_bucket_versioning(False)
s3bucket.is_versioning_suspended()
[10]:
True
4. Delete a bucket¶
Write an object, so the bucket is not empty:
[11]:
(s3bucket / "file.txt").write_text("hello")
[11]:
S3Path('s3://s3pathlib-test-tmp-docs-123456789012/file.txt')
S3 only deletes an empty bucket, with no object, no version and no delete marker. Otherwise delete_bucket raises BucketNotEmpty:
[12]:
import botocore.exceptions
try:
s3bucket.delete_bucket()
except botocore.exceptions.ClientError as e:
print(e.response["Error"]["Code"])
BucketNotEmpty
Empty it first. delete() on a bucket path deletes everything in it, so it asks you to type YES; skip_prompt=True skips the question. Because this bucket had versioning, is_hard_delete=True also deletes the versions and delete markers.
[13]:
s3bucket.delete(is_hard_delete=True, skip_prompt=True)
s3bucket.count_objects()
[13]:
0
[14]:
response = s3bucket.delete_bucket()
s3bucket.exists()
[14]:
False
The bucket methods only work on a bucket path:
[15]:
from s3pathlib.api import exc
try:
S3Path("my-bucket", "folder/").create_bucket()
except exc.S3PathIsNotBucketError as e:
print(f"{type(e).__name__}: {e}")
S3PathIsNotBucketError: 's3://my-bucket/folder/' is not a bucket!
Common pitfalls¶
Bucket names are global. Another AWS account may own the name you want; add something unique, such as your account id.
A bucket must be empty to be deleted, including old versions and delete markers in a bucket that ever had versioning.
Deleting a bucket path deletes everything in it.
S3Path("my-bucket").delete()empties the bucket (after asking);delete_bucket()removes the bucket itself.
See also¶
Versioning: work with the versions of objects.
Clients and Errors: create buckets in another region with a client of that region.