Skip to main content

vintasend-aws-s3-attachments

An AWS S3 attachment manager for vintasend, backed by boto3.

VintaSend splits an attachment into two things: the bytes, owned by an attachment manager, and a row describing them, owned by a notification backend. This package is the manager half: it stores every uploaded file as an object in an S3 bucket and hands the backend an opaque storage_identifiers dict so the backend never has to talk to S3 itself. Pair it with any vintasend backend that supports attachments (vintasend-django, vintasend-sqlalchemy, ...).

Install

poetry add vintasend-aws-s3-attachments
# or
pip install vintasend-aws-s3-attachments

boto3 comes as a dependency. AWS credentials and region are resolved the usual boto3 way (environment variables, ~/.aws/, an instance role, ...), unless you inject a preconfigured client.

Usage

from vintasend.services.notification_service import NotificationService
from vintasend_aws_s3_attachments import S3AttachmentManager

service = NotificationService(
    notification_adapters=[...],
    notification_backend=my_backend,           # any attachment-aware vintasend backend
    attachment_manager=S3AttachmentManager(
        bucket="my-notification-attachments",
        prefix="attachments",                  # optional key prefix ("folder")
    ),
)

Instead of passing an instance, you can point the NOTIFICATION_ATTACHMENT_MANAGER setting at a dotted path and let the service resolve it.

Configuring the S3 client

The manager builds boto3.client("s3") lazily on first use. Steer that with client_kwargs:

S3AttachmentManager(
    bucket="my-bucket",
    client_kwargs={"region_name": "eu-west-1", "endpoint_url": "https://minio.local"},
)

Or inject a client you already built (a shared session, a MinIO/LocalStack endpoint, a custom retry config, and so on):

import boto3

S3AttachmentManager(bucket="my-bucket", client=boto3.client("s3"))

AsyncIO

S3AsyncIOAttachmentManager has the same constructor and mirrors the sync class for AsyncIONotificationService. boto3 is synchronous, so upload_file / delete_file_by_identifiers are async def that wrap boto3's blocking calls; reconstruct_attachment_file stays a plain method (it only builds a lazy handle, doing no I/O), matching the base seam.

How storage identifiers work

upload_file writes the object under a collision-free key (<prefix>/<uuid>_<filename>) and returns an AttachmentFileRecord whose storage_identifiers is:

{"id": key, "bucket": bucket, "key": key}

id is the required, non-empty key every manager must provide; bucket and key are what this manager reads back in reconstruct_attachment_file / delete_file_by_identifiers. A record written without a bucket key (a legacy row) still resolves against the manager's own configured bucket.

The handle returned by reconstruct_attachment_file is an S3StoredFile:

  • read() / stream() fetch the object (a missing object raises FileNotFoundError),
  • url(expires_in=3600) returns a presigned GET URL,
  • delete() removes the object.

Reclaiming orphaned files

VintaSend never deletes stored bytes on its own. To reclaim files no notification references anymore, drive the backend's orphan query and this manager together in a periodic task of your own:

for record in backend.get_orphaned_attachment_files():
    manager.delete_file_by_identifiers(record.storage_identifiers)  # delete the S3 object
    backend.delete_attachment_file(record.id)                       # drop the row

Development

poetry install
poetry run pytest   # tests run fully offline against an in-memory fake S3 client
poetry run ruff check
poetry run mypy

The test suite injects a fake boto3-style client, so no AWS account, credentials, or network access are needed to run it.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vintasend_aws_s3_attachments-3.1.1.tar.gz (6.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vintasend_aws_s3_attachments-3.1.1-py3-none-any.whl (6.4 kB view details)

Uploaded Python 3

File details

Details for the file vintasend_aws_s3_attachments-3.1.1.tar.gz.

File metadata

File hashes

Hashes for vintasend_aws_s3_attachments-3.1.1.tar.gz
Algorithm Hash digest
SHA256 a1cd8da1de69040f1375ee143576eb74d649e11ac3dcc32c47b0ce34c4cb34eb
MD5 8374bedc1b0e5a86708bd1e4c141abc7
BLAKE2b-256 936a886e6d99f19054864d54112835e1e6ebbf550689c1f847a560dec443f5e6

See more details on using hashes here.

Provenance

The following attestation bundles were made for vintasend_aws_s3_attachments-3.1.1.tar.gz:

Publisher: publish.yml on vintasoftware/vintasend-aws-s3-attachments

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vintasend_aws_s3_attachments-3.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for vintasend_aws_s3_attachments-3.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 aa894e1de2de58b86b53835b7cfa1c9d6e65ad6e966088b69eccac62fa54e77a
MD5 6050fadfbef6464c3956a95d2cd830da
BLAKE2b-256 8cfed329e9ec838a28b8d5f953f6a9c687f240123c02e4783b752705284f932d

See more details on using hashes here.

Provenance

The following attestation bundles were made for vintasend_aws_s3_attachments-3.1.1-py3-none-any.whl:

Publisher: publish.yml on vintasoftware/vintasend-aws-s3-attachments

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

3.1.1 This release

2 files

3.1.0

2 files

3.0.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page