mirror of https://github.com/zulip/zulip.git
mypy: Add boto3-stubs.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
parent
bfdb2f4628
commit
1bdb7b1141
|
@ -51,8 +51,6 @@ module = [
|
||||||
"aioapns.*",
|
"aioapns.*",
|
||||||
"bitfield.*",
|
"bitfield.*",
|
||||||
"bmemcached.*",
|
"bmemcached.*",
|
||||||
"boto3.*",
|
|
||||||
"botocore.*",
|
|
||||||
"bs4.*",
|
"bs4.*",
|
||||||
"bson.*",
|
"bson.*",
|
||||||
"cairosvg.*",
|
"cairosvg.*",
|
||||||
|
|
|
@ -36,6 +36,7 @@ SQLAlchemy==1.3.* # 1.4 has badly busted type annotations
|
||||||
|
|
||||||
# Needed for S3 file uploads
|
# Needed for S3 file uploads
|
||||||
boto3
|
boto3
|
||||||
|
mypy-boto3-s3
|
||||||
|
|
||||||
# Needed for integrations
|
# Needed for integrations
|
||||||
defusedxml
|
defusedxml
|
||||||
|
|
|
@ -101,6 +101,10 @@ boto3==1.17.105 \
|
||||||
# via
|
# via
|
||||||
# -r requirements/common.in
|
# -r requirements/common.in
|
||||||
# moto
|
# moto
|
||||||
|
boto3-stubs[s3]==1.18.17 \
|
||||||
|
--hash=sha256:97aef3a2173bedd95b75aafaa1a6a85e321af107a11855f30afded7a1e2462bc \
|
||||||
|
--hash=sha256:b5bd2f3f54f06eecb9f6a085643c4c02a057c5fbbad4256c4e4a02a0744758df
|
||||||
|
# via -r requirements/mypy.in
|
||||||
botocore==1.20.105 \
|
botocore==1.20.105 \
|
||||||
--hash=sha256:b0fda4edf8eb105453890700d49011ada576d0cc7326a0699dfabe9e872f552c \
|
--hash=sha256:b0fda4edf8eb105453890700d49011ada576d0cc7326a0699dfabe9e872f552c \
|
||||||
--hash=sha256:b5ba72d22212b0355f339c2a98b3296b3b2202a48e6a2b1366e866bc65a64b67
|
--hash=sha256:b5ba72d22212b0355f339c2a98b3296b3b2202a48e6a2b1366e866bc65a64b67
|
||||||
|
@ -108,6 +112,10 @@ botocore==1.20.105 \
|
||||||
# boto3
|
# boto3
|
||||||
# moto
|
# moto
|
||||||
# s3transfer
|
# s3transfer
|
||||||
|
botocore-stubs==1.21.17 \
|
||||||
|
--hash=sha256:6fca2ff326532e8ad8b74c1e5ef6e0457f409ebe38cb8b4aa6cb50b534ee3ee3 \
|
||||||
|
--hash=sha256:b754cb23471948b8cbe50d24d4a74c617672905e4ae170b01bcfcae6496d7cb6
|
||||||
|
# via boto3-stubs
|
||||||
cachetools==4.2.2 \
|
cachetools==4.2.2 \
|
||||||
--hash=sha256:2cc0b89715337ab6dbba85b5b50effe2b0c74e035d83ee8ed637cf52f12ae001 \
|
--hash=sha256:2cc0b89715337ab6dbba85b5b50effe2b0c74e035d83ee8ed637cf52f12ae001 \
|
||||||
--hash=sha256:61b5ed1e22a0924aed1d23b478f37e8d52549ff8a961de2909c69bf950020cff
|
--hash=sha256:61b5ed1e22a0924aed1d23b478f37e8d52549ff8a961de2909c69bf950020cff
|
||||||
|
@ -788,6 +796,12 @@ mypy==0.910 \
|
||||||
# via
|
# via
|
||||||
# -r requirements/mypy.in
|
# -r requirements/mypy.in
|
||||||
# sqlalchemy-stubs
|
# sqlalchemy-stubs
|
||||||
|
mypy-boto3-s3==1.18.17 \
|
||||||
|
--hash=sha256:63a76e94df730984196fd46be3f541dacc8d162f6f70c210a4cd9a80d6775e3b \
|
||||||
|
--hash=sha256:af3699fb37614ff8044b7b6d3d7dd2211e5307bf018ac4f0a3591ec2011123c1
|
||||||
|
# via
|
||||||
|
# -r requirements/common.in
|
||||||
|
# boto3-stubs
|
||||||
mypy-extensions==0.4.3 \
|
mypy-extensions==0.4.3 \
|
||||||
--hash=sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d \
|
--hash=sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d \
|
||||||
--hash=sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8
|
--hash=sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8
|
||||||
|
@ -1742,9 +1756,12 @@ typing-extensions==3.10.0.0 \
|
||||||
# arrow
|
# arrow
|
||||||
# asgiref
|
# asgiref
|
||||||
# black
|
# black
|
||||||
|
# boto3-stubs
|
||||||
|
# botocore-stubs
|
||||||
# importlib-metadata
|
# importlib-metadata
|
||||||
# libcst
|
# libcst
|
||||||
# mypy
|
# mypy
|
||||||
|
# mypy-boto3-s3
|
||||||
# pyre-check
|
# pyre-check
|
||||||
# pyre-extensions
|
# pyre-extensions
|
||||||
# sqlalchemy-stubs
|
# sqlalchemy-stubs
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
mypy
|
mypy
|
||||||
|
|
||||||
backoff-stubs
|
backoff-stubs
|
||||||
|
boto3-stubs[s3]
|
||||||
lxml-stubs
|
lxml-stubs
|
||||||
https://github.com/andersk/pika-stubs/archive/87c5795741449e37bdbd2ceceee853fd56462440.zip#egg=pika-stubs==0.1.3+git # https://github.com/hahow/pika-stubs/issues/1, https://github.com/hahow/pika-stubs/pull/4
|
https://github.com/andersk/pika-stubs/archive/87c5795741449e37bdbd2ceceee853fd56462440.zip#egg=pika-stubs==0.1.3+git # https://github.com/hahow/pika-stubs/issues/1, https://github.com/hahow/pika-stubs/pull/4
|
||||||
sqlalchemy-stubs
|
sqlalchemy-stubs
|
||||||
|
|
|
@ -10,6 +10,14 @@
|
||||||
backoff-stubs==1.10.0 \
|
backoff-stubs==1.10.0 \
|
||||||
--hash=sha256:03e995de0a70016c6fe758498e1ca811f1db517c00cbd06e3039c9e4f6ea2566
|
--hash=sha256:03e995de0a70016c6fe758498e1ca811f1db517c00cbd06e3039c9e4f6ea2566
|
||||||
# via -r requirements/mypy.in
|
# via -r requirements/mypy.in
|
||||||
|
boto3-stubs[s3]==1.18.17 \
|
||||||
|
--hash=sha256:97aef3a2173bedd95b75aafaa1a6a85e321af107a11855f30afded7a1e2462bc \
|
||||||
|
--hash=sha256:b5bd2f3f54f06eecb9f6a085643c4c02a057c5fbbad4256c4e4a02a0744758df
|
||||||
|
# via -r requirements/mypy.in
|
||||||
|
botocore-stubs==1.21.17 \
|
||||||
|
--hash=sha256:6fca2ff326532e8ad8b74c1e5ef6e0457f409ebe38cb8b4aa6cb50b534ee3ee3 \
|
||||||
|
--hash=sha256:b754cb23471948b8cbe50d24d4a74c617672905e4ae170b01bcfcae6496d7cb6
|
||||||
|
# via boto3-stubs
|
||||||
lxml-stubs==0.2.0 \
|
lxml-stubs==0.2.0 \
|
||||||
--hash=sha256:78f1bfb31b1f2af9a5c9e9a602ab1b589a64a5a3cc444931a39cdfd02d6864b0 \
|
--hash=sha256:78f1bfb31b1f2af9a5c9e9a602ab1b589a64a5a3cc444931a39cdfd02d6864b0 \
|
||||||
--hash=sha256:f0b3621ec2a23bea4145f484490c8b27383ecb407b3f8b079199ad4a0af4180b
|
--hash=sha256:f0b3621ec2a23bea4145f484490c8b27383ecb407b3f8b079199ad4a0af4180b
|
||||||
|
@ -41,6 +49,10 @@ mypy==0.910 \
|
||||||
# via
|
# via
|
||||||
# -r requirements/mypy.in
|
# -r requirements/mypy.in
|
||||||
# sqlalchemy-stubs
|
# sqlalchemy-stubs
|
||||||
|
mypy-boto3-s3==1.18.17 \
|
||||||
|
--hash=sha256:63a76e94df730984196fd46be3f541dacc8d162f6f70c210a4cd9a80d6775e3b \
|
||||||
|
--hash=sha256:af3699fb37614ff8044b7b6d3d7dd2211e5307bf018ac4f0a3591ec2011123c1
|
||||||
|
# via boto3-stubs
|
||||||
mypy-extensions==0.4.3 \
|
mypy-extensions==0.4.3 \
|
||||||
--hash=sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d \
|
--hash=sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d \
|
||||||
--hash=sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8
|
--hash=sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8
|
||||||
|
@ -179,5 +191,6 @@ typing-extensions==3.10.0.0 \
|
||||||
--hash=sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342 \
|
--hash=sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342 \
|
||||||
--hash=sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84
|
--hash=sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84
|
||||||
# via
|
# via
|
||||||
|
# boto3-stubs
|
||||||
# mypy
|
# mypy
|
||||||
# sqlalchemy-stubs
|
# sqlalchemy-stubs
|
||||||
|
|
|
@ -494,6 +494,10 @@ more-itertools==8.8.0 \
|
||||||
--hash=sha256:2cf89ec599962f2ddc4d568a05defc40e0a587fbc10d5989713638864c36be4d \
|
--hash=sha256:2cf89ec599962f2ddc4d568a05defc40e0a587fbc10d5989713638864c36be4d \
|
||||||
--hash=sha256:83f0308e05477c68f56ea3a888172c78ed5d5b3c282addb67508e7ba6c8f813a
|
--hash=sha256:83f0308e05477c68f56ea3a888172c78ed5d5b3c282addb67508e7ba6c8f813a
|
||||||
# via openapi-core
|
# via openapi-core
|
||||||
|
mypy-boto3-s3==1.18.17 \
|
||||||
|
--hash=sha256:63a76e94df730984196fd46be3f541dacc8d162f6f70c210a4cd9a80d6775e3b \
|
||||||
|
--hash=sha256:af3699fb37614ff8044b7b6d3d7dd2211e5307bf018ac4f0a3591ec2011123c1
|
||||||
|
# via -r requirements/common.in
|
||||||
oauthlib==3.1.1 \
|
oauthlib==3.1.1 \
|
||||||
--hash=sha256:42bf6354c2ed8c6acb54d971fce6f88193d97297e18602a3a886603f9d7730cc \
|
--hash=sha256:42bf6354c2ed8c6acb54d971fce6f88193d97297e18602a3a886603f9d7730cc \
|
||||||
--hash=sha256:8f0215fcc533dd8dd1bee6f4c412d4f0cd7297307d43ac61666389e3bc3198a3
|
--hash=sha256:8f0215fcc533dd8dd1bee6f4c412d4f0cd7297307d43ac61666389e3bc3198a3
|
||||||
|
@ -1046,6 +1050,7 @@ typing-extensions==3.10.0.0 \
|
||||||
# -r requirements/common.in
|
# -r requirements/common.in
|
||||||
# asgiref
|
# asgiref
|
||||||
# importlib-metadata
|
# importlib-metadata
|
||||||
|
# mypy-boto3-s3
|
||||||
# zulip-bots
|
# zulip-bots
|
||||||
uhashring==2.1 \
|
uhashring==2.1 \
|
||||||
--hash=sha256:b21340d0d32497a67f34f5177a64908115fdc23264ed87fa7d1eca79ef9641fa
|
--hash=sha256:b21340d0d32497a67f34f5177a64908115fdc23264ed87fa7d1eca79ef9641fa
|
||||||
|
|
|
@ -48,4 +48,4 @@ API_FEATURE_LEVEL = 92
|
||||||
# historical commits sharing the same major version, in which case a
|
# historical commits sharing the same major version, in which case a
|
||||||
# minor version bump suffices.
|
# minor version bump suffices.
|
||||||
|
|
||||||
PROVISION_VERSION = "153.13"
|
PROVISION_VERSION = "153.14"
|
||||||
|
|
|
@ -16,12 +16,12 @@ import tempfile
|
||||||
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
|
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
|
||||||
|
|
||||||
import orjson
|
import orjson
|
||||||
from boto3.resources.base import ServiceResource
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.forms.models import model_to_dict
|
from django.forms.models import model_to_dict
|
||||||
from django.utils.timezone import is_naive as timezone_is_naive
|
from django.utils.timezone import is_naive as timezone_is_naive
|
||||||
from django.utils.timezone import make_aware as timezone_make_aware
|
from django.utils.timezone import make_aware as timezone_make_aware
|
||||||
|
from mypy_boto3_s3.service_resource import Object
|
||||||
|
|
||||||
import zerver.lib.upload
|
import zerver.lib.upload
|
||||||
from analytics.models import RealmCount, StreamCount, UserCount
|
from analytics.models import RealmCount, StreamCount, UserCount
|
||||||
|
@ -1275,7 +1275,7 @@ def export_uploads_and_avatars(realm: Realm, output_dir: Path) -> None:
|
||||||
|
|
||||||
def _check_key_metadata(
|
def _check_key_metadata(
|
||||||
email_gateway_bot: Optional[UserProfile],
|
email_gateway_bot: Optional[UserProfile],
|
||||||
key: ServiceResource,
|
key: Object,
|
||||||
processing_avatars: bool,
|
processing_avatars: bool,
|
||||||
realm: Realm,
|
realm: Realm,
|
||||||
user_ids: Set[int],
|
user_ids: Set[int],
|
||||||
|
@ -1298,10 +1298,10 @@ def _check_key_metadata(
|
||||||
|
|
||||||
|
|
||||||
def _get_exported_s3_record(
|
def _get_exported_s3_record(
|
||||||
bucket_name: str, key: ServiceResource, processing_emoji: bool
|
bucket_name: str, key: Object, processing_emoji: bool
|
||||||
) -> Dict[str, Union[str, int]]:
|
) -> Dict[str, Any]:
|
||||||
# Helper function for export_files_from_s3
|
# Helper function for export_files_from_s3
|
||||||
record = dict(
|
record: Dict[str, Any] = dict(
|
||||||
s3_path=key.key,
|
s3_path=key.key,
|
||||||
bucket=bucket_name,
|
bucket=bucket_name,
|
||||||
size=key.content_length,
|
size=key.content_length,
|
||||||
|
@ -1315,7 +1315,7 @@ def _get_exported_s3_record(
|
||||||
record["file_name"] = os.path.basename(key.key)
|
record["file_name"] = os.path.basename(key.key)
|
||||||
|
|
||||||
if "user_profile_id" in record:
|
if "user_profile_id" in record:
|
||||||
user_profile = get_user_profile_by_id(record["user_profile_id"])
|
user_profile = get_user_profile_by_id(int(record["user_profile_id"]))
|
||||||
record["user_profile_email"] = user_profile.email
|
record["user_profile_email"] = user_profile.email
|
||||||
|
|
||||||
# Fix the record ids
|
# Fix the record ids
|
||||||
|
@ -1340,7 +1340,7 @@ def _get_exported_s3_record(
|
||||||
|
|
||||||
|
|
||||||
def _save_s3_object_to_file(
|
def _save_s3_object_to_file(
|
||||||
key: ServiceResource,
|
key: Object,
|
||||||
output_dir: str,
|
output_dir: str,
|
||||||
processing_avatars: bool,
|
processing_avatars: bool,
|
||||||
processing_emoji: bool,
|
processing_emoji: bool,
|
||||||
|
@ -1365,7 +1365,7 @@ def _save_s3_object_to_file(
|
||||||
|
|
||||||
if not os.path.exists(dirname):
|
if not os.path.exists(dirname):
|
||||||
os.makedirs(dirname)
|
os.makedirs(dirname)
|
||||||
key.download_file(filename)
|
key.download_file(Filename=filename)
|
||||||
|
|
||||||
|
|
||||||
def export_files_from_s3(
|
def export_files_from_s3(
|
||||||
|
|
|
@ -823,7 +823,7 @@ def import_uploads(
|
||||||
content_type = "application/octet-stream"
|
content_type = "application/octet-stream"
|
||||||
|
|
||||||
key.upload_file(
|
key.upload_file(
|
||||||
os.path.join(import_dir, record["path"]),
|
Filename=os.path.join(import_dir, record["path"]),
|
||||||
ExtraArgs={"ContentType": content_type, "Metadata": metadata},
|
ExtraArgs={"ContentType": content_type, "Metadata": metadata},
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -28,7 +28,6 @@ import boto3
|
||||||
import fakeldap
|
import fakeldap
|
||||||
import ldap
|
import ldap
|
||||||
import orjson
|
import orjson
|
||||||
from boto3.resources.base import ServiceResource
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import AnonymousUser
|
from django.contrib.auth.models import AnonymousUser
|
||||||
from django.db.migrations.state import StateApps
|
from django.db.migrations.state import StateApps
|
||||||
|
@ -37,6 +36,7 @@ from django.http.request import QueryDict
|
||||||
from django.test import override_settings
|
from django.test import override_settings
|
||||||
from django.urls import URLResolver
|
from django.urls import URLResolver
|
||||||
from moto import mock_s3
|
from moto import mock_s3
|
||||||
|
from mypy_boto3_s3.service_resource import Bucket
|
||||||
|
|
||||||
import zerver.lib.upload
|
import zerver.lib.upload
|
||||||
from zerver.lib import cache
|
from zerver.lib import cache
|
||||||
|
@ -521,7 +521,7 @@ def use_s3_backend(method: FuncT) -> FuncT:
|
||||||
return new_method
|
return new_method
|
||||||
|
|
||||||
|
|
||||||
def create_s3_buckets(*bucket_names: str) -> List[ServiceResource]:
|
def create_s3_buckets(*bucket_names: str) -> List[Bucket]:
|
||||||
session = boto3.Session(settings.S3_KEY, settings.S3_SECRET_KEY)
|
session = boto3.Session(settings.S3_KEY, settings.S3_SECRET_KEY)
|
||||||
s3 = session.resource("s3")
|
s3 = session.resource("s3")
|
||||||
buckets = [s3.create_bucket(Bucket=name) for name in bucket_names]
|
buckets = [s3.create_bucket(Bucket=name) for name in bucket_names]
|
||||||
|
|
|
@ -15,7 +15,6 @@ from typing import Any, Callable, Optional, Tuple
|
||||||
|
|
||||||
import boto3
|
import boto3
|
||||||
import botocore
|
import botocore
|
||||||
from boto3.resources.base import ServiceResource
|
|
||||||
from boto3.session import Session
|
from boto3.session import Session
|
||||||
from botocore.client import Config
|
from botocore.client import Config
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -25,6 +24,8 @@ from django.http import HttpRequest
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from jinja2.utils import Markup as mark_safe
|
from jinja2.utils import Markup as mark_safe
|
||||||
|
from mypy_boto3_s3.client import S3Client
|
||||||
|
from mypy_boto3_s3.service_resource import Bucket, Object
|
||||||
from PIL import Image, ImageOps
|
from PIL import Image, ImageOps
|
||||||
from PIL.GifImagePlugin import GifImageFile
|
from PIL.GifImagePlugin import GifImageFile
|
||||||
from PIL.Image import DecompressionBombError
|
from PIL.Image import DecompressionBombError
|
||||||
|
@ -278,9 +279,7 @@ class ZulipUploadBackend:
|
||||||
### S3
|
### S3
|
||||||
|
|
||||||
|
|
||||||
def get_bucket(bucket_name: str, session: Optional[Session] = None) -> ServiceResource:
|
def get_bucket(bucket_name: str, session: Optional[Session] = None) -> Bucket:
|
||||||
# See https://github.com/python/typeshed/issues/2706
|
|
||||||
# for why this return type is a `ServiceResource`.
|
|
||||||
if session is None:
|
if session is None:
|
||||||
session = boto3.Session(settings.S3_KEY, settings.S3_SECRET_KEY)
|
session = boto3.Session(settings.S3_KEY, settings.S3_SECRET_KEY)
|
||||||
bucket = session.resource(
|
bucket = session.resource(
|
||||||
|
@ -290,8 +289,7 @@ def get_bucket(bucket_name: str, session: Optional[Session] = None) -> ServiceRe
|
||||||
|
|
||||||
|
|
||||||
def upload_image_to_s3(
|
def upload_image_to_s3(
|
||||||
# See https://github.com/python/typeshed/issues/2706
|
bucket: Bucket,
|
||||||
bucket: ServiceResource,
|
|
||||||
file_name: str,
|
file_name: str,
|
||||||
content_type: Optional[str],
|
content_type: Optional[str],
|
||||||
user_profile: UserProfile,
|
user_profile: UserProfile,
|
||||||
|
@ -367,7 +365,7 @@ class S3UploadBackend(ZulipUploadBackend):
|
||||||
self.avatar_bucket = get_bucket(settings.S3_AVATAR_BUCKET, self.session)
|
self.avatar_bucket = get_bucket(settings.S3_AVATAR_BUCKET, self.session)
|
||||||
self.uploads_bucket = get_bucket(settings.S3_AUTH_UPLOADS_BUCKET, self.session)
|
self.uploads_bucket = get_bucket(settings.S3_AUTH_UPLOADS_BUCKET, self.session)
|
||||||
|
|
||||||
self._boto_client = None
|
self._boto_client: Optional[S3Client] = None
|
||||||
self.public_upload_url_base = self.construct_public_upload_url_base()
|
self.public_upload_url_base = self.construct_public_upload_url_base()
|
||||||
|
|
||||||
def construct_public_upload_url_base(self) -> str:
|
def construct_public_upload_url_base(self) -> str:
|
||||||
|
@ -410,7 +408,7 @@ class S3UploadBackend(ZulipUploadBackend):
|
||||||
assert not key.startswith("/")
|
assert not key.startswith("/")
|
||||||
return urllib.parse.urljoin(self.public_upload_url_base, key)
|
return urllib.parse.urljoin(self.public_upload_url_base, key)
|
||||||
|
|
||||||
def get_boto_client(self) -> botocore.client.BaseClient:
|
def get_boto_client(self) -> S3Client:
|
||||||
"""
|
"""
|
||||||
Creating the client takes a long time so we need to cache it.
|
Creating the client takes a long time so we need to cache it.
|
||||||
"""
|
"""
|
||||||
|
@ -424,7 +422,7 @@ class S3UploadBackend(ZulipUploadBackend):
|
||||||
)
|
)
|
||||||
return self._boto_client
|
return self._boto_client
|
||||||
|
|
||||||
def delete_file_from_s3(self, path_id: str, bucket: ServiceResource) -> bool:
|
def delete_file_from_s3(self, path_id: str, bucket: Bucket) -> bool:
|
||||||
key = bucket.Object(path_id)
|
key = bucket.Object(path_id)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -532,9 +530,7 @@ class S3UploadBackend(ZulipUploadBackend):
|
||||||
self.delete_file_from_s3(path_id + "-medium.png", self.avatar_bucket)
|
self.delete_file_from_s3(path_id + "-medium.png", self.avatar_bucket)
|
||||||
self.delete_file_from_s3(path_id, self.avatar_bucket)
|
self.delete_file_from_s3(path_id, self.avatar_bucket)
|
||||||
|
|
||||||
def get_avatar_key(self, file_name: str) -> ServiceResource:
|
def get_avatar_key(self, file_name: str) -> Object:
|
||||||
# See https://github.com/python/typeshed/issues/2706
|
|
||||||
# for why this return type is a `ServiceResource`.
|
|
||||||
key = self.avatar_bucket.Object(file_name)
|
key = self.avatar_bucket.Object(file_name)
|
||||||
return key
|
return key
|
||||||
|
|
||||||
|
@ -693,7 +689,10 @@ class S3UploadBackend(ZulipUploadBackend):
|
||||||
os.path.join("exports", secrets.token_hex(16), os.path.basename(tarball_path))
|
os.path.join("exports", secrets.token_hex(16), os.path.basename(tarball_path))
|
||||||
)
|
)
|
||||||
|
|
||||||
key.upload_file(tarball_path, Callback=percent_callback)
|
if percent_callback is None:
|
||||||
|
key.upload_file(Filename=tarball_path)
|
||||||
|
else:
|
||||||
|
key.upload_file(Filename=tarball_path, Callback=percent_callback)
|
||||||
|
|
||||||
public_url = self.get_public_upload_url(key.key)
|
public_url = self.get_public_upload_url(key.key)
|
||||||
return public_url
|
return public_url
|
||||||
|
|
|
@ -6,6 +6,7 @@ from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
from django.db.backends.postgresql.schema import DatabaseSchemaEditor
|
from django.db.backends.postgresql.schema import DatabaseSchemaEditor
|
||||||
from django.db.migrations.state import StateApps
|
from django.db.migrations.state import StateApps
|
||||||
|
from mypy_boto3_s3.type_defs import CopySourceTypeDef
|
||||||
|
|
||||||
|
|
||||||
class Uploader:
|
class Uploader:
|
||||||
|
@ -66,8 +67,8 @@ class S3Uploader(Uploader):
|
||||||
).Bucket(self.bucket_name)
|
).Bucket(self.bucket_name)
|
||||||
|
|
||||||
def copy_files(self, src_key: str, dst_key: str) -> None:
|
def copy_files(self, src_key: str, dst_key: str) -> None:
|
||||||
source = dict(Bucket=self.bucket_name, Key=src_key)
|
source = CopySourceTypeDef(Bucket=self.bucket_name, Key=src_key)
|
||||||
self.bucket.copy(source, dst_key)
|
self.bucket.copy(CopySource=source, Key=dst_key)
|
||||||
|
|
||||||
|
|
||||||
def get_uploader() -> Uploader:
|
def get_uploader() -> Uploader:
|
||||||
|
|
Loading…
Reference in New Issue