Skip to content

Commit 1a2bf20

Browse files
committed
add stricter type checking
1 parent ade7d81 commit 1a2bf20

File tree

6 files changed

+30
-28
lines changed

6 files changed

+30
-28
lines changed

minio_storage/files.py

+11-7
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from minio_storage.errors import minio_error
99

1010
if T.TYPE_CHECKING:
11-
from minio_storage.storage import Storage
11+
from minio_storage.storage import MinioStorage
1212

1313
logger = getLogger("minio_storage")
1414

@@ -36,8 +36,8 @@ def seek(self, *args, **kwargs) -> bool:
3636

3737

3838
class MinioStorageFile(File):
39-
def __init__(self, name: str, mode: str, storage: "Storage", **kwargs):
40-
self._storage: "Storage" = storage
39+
def __init__(self, name: str, mode: str, storage: "MinioStorage", **kwargs):
40+
self._storage: "MinioStorage" = storage
4141
self.name: str = name
4242
self._mode: str = mode
4343
self._file = None
@@ -52,7 +52,7 @@ def __init__(
5252
self,
5353
name: str,
5454
mode: str,
55-
storage: "Storage",
55+
storage: "MinioStorage",
5656
max_memory_size: T.Optional[int] = None,
5757
**kwargs,
5858
):
@@ -66,6 +66,7 @@ def __init__(
6666

6767
@property
6868
def file(self):
69+
obj = None
6970
if self._file is None:
7071
try:
7172
obj = self._storage.client.get_object(
@@ -78,7 +79,8 @@ def file(self):
7879
raise OSError(f"File {self.name} does not exist")
7980
finally:
8081
try:
81-
obj.release_conn()
82+
if obj:
83+
obj.release_conn()
8284
except Exception as e:
8385
logger.error(str(e))
8486
return self._file
@@ -104,7 +106,7 @@ def __init__(
104106
self,
105107
name: str,
106108
mode: str,
107-
storage: "Storage",
109+
storage: "MinioStorage",
108110
max_memory_size: T.Optional[int] = None,
109111
**kwargs,
110112
):
@@ -119,6 +121,7 @@ def __init__(
119121
@property
120122
def file(self):
121123
if self._file is None:
124+
obj = None
122125
try:
123126
obj = self._storage.client.get_object(
124127
self._storage.bucket_name, self.name
@@ -134,7 +137,8 @@ def file(self):
134137
raise minio_error(f"File {self.name} does not exist", error)
135138
finally:
136139
try:
137-
obj.release_conn()
140+
if obj:
141+
obj.release_conn()
138142
except Exception as e:
139143
logger.error(str(e))
140144
return self._file

minio_storage/management/commands/minio.py

+1-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import argparse
21
import json
32
import sys
43
import typing as T
@@ -46,12 +45,8 @@ def add_arguments(self, parser):
4645
description="valid subcommands",
4746
# required=True,
4847
)
49-
cmds._parser_class = argparse.ArgumentParser # circumvent Django 1.11 bug
50-
5148
cmds.add_parser(self.CHECK, help="check bucket")
52-
5349
cmds.add_parser(self.CREATE, help="make bucket")
54-
5550
cmds.add_parser(self.DELETE, help="remove an empty bucket")
5651

5752
ls = cmds.add_parser(self.LIST, help="list bucket objects or buckets")
@@ -141,7 +136,7 @@ def storage(self, options):
141136

142137
# TODO: maybe another way
143138
with patch.object(storage_class, "_init_check", return_value=None):
144-
storage = storage_class()
139+
storage = storage_class() # type: ignore
145140
return storage
146141

147142
def bucket_exists(self, storage, bucket_name):

minio_storage/storage.py

+12-10
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from django.core.files.storage import Storage
1313
from django.utils import timezone
1414
from django.utils.deconstruct import deconstructible
15+
from minio.datatypes import Object
1516

1617
from minio_storage.errors import minio_error
1718
from minio_storage.files import ReadOnlySpooledTemporaryFile
@@ -106,12 +107,9 @@ def _create_base_url_client(client: minio.Minio, bucket_name: str, base_url: str
106107
base_url_parts = urlsplit(base_url)
107108

108109
# Clone from the normal client, but with base_url as the endpoint
109-
credentials = client._provider.retrieve()
110110
base_url_client = minio.Minio(
111111
base_url_parts.netloc,
112-
access_key=credentials.access_key,
113-
secret_key=credentials.secret_key,
114-
session_token=credentials.session_token,
112+
credentials=client._provider,
115113
secure=base_url_parts.scheme == "https",
116114
# The bucket region may be auto-detected by client (via an HTTP
117115
# request), so don't just use client._region
@@ -250,8 +248,8 @@ def listdir(self, path: str) -> T.Tuple[T.List, T.List]:
250248

251249
def size(self, name: str) -> int:
252250
try:
253-
info = self.client.stat_object(self.bucket_name, name)
254-
return info.size
251+
info: Object = self.client.stat_object(self.bucket_name, name)
252+
return info.size # type: ignore
255253
except merr.InvalidResponseError as error:
256254
raise minio_error(f"Could not access file size for {name}", error)
257255

@@ -293,7 +291,7 @@ def _presigned_url(
293291

294292
def url(
295293
self, name: str, *args, max_age: T.Optional[datetime.timedelta] = None
296-
) -> T.Optional[str]:
294+
) -> str:
297295
url = ""
298296
if self.presign_urls:
299297
url = self._presigned_url(name, max_age=max_age)
@@ -317,7 +315,9 @@ def strip_end(path):
317315
self.bucket_name,
318316
quote(strip_beg(name)),
319317
)
320-
return url
318+
if url:
319+
return url
320+
raise OSError(f"could not produce URL for {name}")
321321

322322
@property
323323
def endpoint_url(self):
@@ -337,12 +337,14 @@ def created_time(self, name: str) -> datetime.datetime:
337337

338338
def modified_time(self, name: str) -> datetime.datetime:
339339
try:
340-
info = self.client.stat_object(self.bucket_name, name)
341-
return info.last_modified
340+
info: Object = self.client.stat_object(self.bucket_name, name)
341+
if info.last_modified:
342+
return info.last_modified # type: ignore
342343
except merr.InvalidResponseError as error:
343344
raise minio_error(
344345
f"Could not access modification time for file {name}", error
345346
)
347+
raise OSError(f"Could not access modification time for file {name}")
346348

347349

348350
_NoValue = object()

tests/test_app/tests/custom_storage_class_tests.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -96,14 +96,15 @@ def test_custom_storage(self):
9696
) as storage_file:
9797
# Copy the stream from the http stream to the out_file
9898
#
99-
shutil.copyfileobj(storage_file.file, out_file)
99+
shutil.copyfileobj(storage_file.file, out_file) # type: ignore
100100

101101
#
102102
# We are not using the ReadOnlyMinioObjectFile type so we can't seek in
103103
# it.
104104
#
105105
with self.assertRaises(io.UnsupportedOperation):
106-
storage_file.file.seek()
106+
if storage_file.file:
107+
storage_file.file.seek(0)
107108

108109
workspace_files = os.listdir(workspace)
109110
print(workspace_files) # prints: ['secret.txt']

tests/test_app/tests/upload_tests.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def test_metadata(self):
9292
"X-Xss-Protection",
9393
"Date",
9494
}
95-
self.assertTrue(metadata_attrs.issubset(res.metadata.keys()))
95+
self.assertTrue(metadata_attrs.issubset(res.metadata.keys())) # type: ignore
9696

9797

9898
@override_settings(
@@ -105,4 +105,4 @@ def test_default_metadata(self):
105105
self.media_storage.bucket_name, ivan
106106
)
107107

108-
self.assertEqual(res.metadata["Cache-Control"], "max-age=1000")
108+
self.assertEqual(res.metadata["Cache-Control"], "max-age=1000") # type: ignore

tox.ini

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ deps =
5555
django-stubs==4.2.0
5656
-rdev-requirements.txt
5757
commands =
58-
pyright --skipunannotated --level WARNING
58+
pyright --level WARNING
5959

6060

6161
[testenv:lint]

0 commit comments

Comments
 (0)