Python (boto3)
Upload, list, download and delete Shelby objects with boto3.
Prefer to run it? shelby-quickstart has this page as a script that checks every step and cleans up after itself.
Before you start
- Python 3.10 or later, with
pip install boto3
Copy your bucket name, and an access key ID and secret for that bucket, from the console. Export them so the commands below can use them:
export SHELBY_ACCESS_KEY_ID="<your access key ID, SHLB…>"
export SHELBY_SECRET_ACCESS_KEY="<your secret>"
export SHELBY_BUCKET="<your bucket name>"Create a client
import os
import boto3
from botocore.config import Config
s3 = boto3.client(
"s3",
endpoint_url="https://s3.beta.shelby.xyz",
aws_access_key_id=os.environ["SHELBY_ACCESS_KEY_ID"],
aws_secret_access_key=os.environ["SHELBY_SECRET_ACCESS_KEY"],
region_name="default",
config=Config(
s3={"addressing_style": "path"},
request_checksum_calculation="when_required",
),
)
bucket = os.environ["SHELBY_BUCKET"]request_checksum_calculation stops boto3 from sending uploads in aws-chunked framing,
which it does by default (botocore 1.36 and later) and Shelby doesn't accept yet. Without
it, uploads fail with 501 NotImplemented.
Upload and read back
import hashlib
body = b"Hello, Shelby\n"
s3.put_object(Bucket=bucket, Key="examples/hello.txt", Body=body)
data = s3.get_object(Bucket=bucket, Key="examples/hello.txt")["Body"].read()
assert hashlib.sha256(data).digest() == hashlib.sha256(body).digest()
# A new object can take a few seconds to appear in listings.
for obj in s3.list_objects_v2(Bucket=bucket, Prefix="examples/").get("Contents", []):
print(obj["Key"], obj["Size"])Share a download link
import urllib.request
url = s3.generate_presigned_url(
"get_object",
Params={"Bucket": bucket, "Key": "examples/hello.txt"},
ExpiresIn=300,
)
with urllib.request.urlopen(url) as response: # sends no credentials
print(response.read().decode())Anyone with url can download the object for the next 5 minutes, without credentials. The
link works because the client signs with region_name="default". Until it expires, treat the
link like a password. See Presigned URLs.
Clean up
s3.delete_object(Bucket=bucket, Key="examples/hello.txt")Upload large files
upload_file switches to multipart automatically, in 8 MiB parts by default. Set a part size
of at least 10 MiB, because smaller parts each count as 10 MiB of storage, and large
enough for your largest file to fit in Shelby's 3,000 parts:
from boto3.s3.transfer import TransferConfig
s3.upload_file(
"dataset.parquet",
bucket,
"data/dataset.parquet",
Config=TransferConfig(multipart_chunksize=64 * 1024 * 1024), # 64 MiB parts
)64 MiB parts fit files up to about 187 GiB.
What's different with boto3
copy_objectands3.copyfail with501. Shelby has no server-side copy. Download and upload again.- Paginators need
PageSizeof 1,000 or less. Larger values are rejected.