Skip to content

Commit ed63bd8

Browse files
authored
[s3] switch to clean_name util (#1198)
1 parent 981fe2b commit ed63bd8

File tree

2 files changed

+10
-51
lines changed

2 files changed

+10
-51
lines changed

storages/backends/s3boto3.py

+10-23
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from storages.compress import CompressedFileMixin
2424
from storages.compress import CompressStorageMixin
2525
from storages.utils import check_location
26+
from storages.utils import clean_name
2627
from storages.utils import get_available_overwrite_name
2728
from storages.utils import is_seekable
2829
from storages.utils import lookup_env
@@ -406,20 +407,6 @@ def _get_security_token(self):
406407
security_token = self.security_token or lookup_env(self.security_token_names)
407408
return security_token
408409

409-
def _clean_name(self, name):
410-
"""
411-
Cleans the name so that Windows style paths work
412-
"""
413-
# Normalize Windows style paths
414-
clean_name = posixpath.normpath(name).replace('\\', '/')
415-
416-
# os.path.normpath() can strip trailing slashes so we implement
417-
# a workaround here.
418-
if name.endswith('/') and not clean_name.endswith('/'):
419-
# Add a trailing slash as it was stripped.
420-
clean_name += '/'
421-
return clean_name
422-
423410
def _normalize_name(self, name):
424411
"""
425412
Normalizes the name so that paths like /path/to/ignored/../something.txt
@@ -432,7 +419,7 @@ def _normalize_name(self, name):
432419
raise SuspiciousOperation("Attempted access to '%s' denied." % name)
433420

434421
def _open(self, name, mode='rb'):
435-
name = self._normalize_name(self._clean_name(name))
422+
name = self._normalize_name(clean_name(name))
436423
try:
437424
f = S3Boto3StorageFile(name, mode, self)
438425
except ClientError as err:
@@ -442,7 +429,7 @@ def _open(self, name, mode='rb'):
442429
return f
443430

444431
def _save(self, name, content):
445-
cleaned_name = self._clean_name(name)
432+
cleaned_name = clean_name(name)
446433
name = self._normalize_name(cleaned_name)
447434
params = self._get_write_parameters(name, content)
448435

@@ -459,11 +446,11 @@ def _save(self, name, content):
459446
return cleaned_name
460447

461448
def delete(self, name):
462-
name = self._normalize_name(self._clean_name(name))
449+
name = self._normalize_name(clean_name(name))
463450
self.bucket.Object(name).delete()
464451

465452
def exists(self, name):
466-
name = self._normalize_name(self._clean_name(name))
453+
name = self._normalize_name(clean_name(name))
467454
try:
468455
self.connection.meta.client.head_object(Bucket=self.bucket_name, Key=name)
469456
return True
@@ -475,7 +462,7 @@ def exists(self, name):
475462
raise
476463

477464
def listdir(self, name):
478-
path = self._normalize_name(self._clean_name(name))
465+
path = self._normalize_name(clean_name(name))
479466
# The path needs to end with a slash, but if the root is empty, leave it.
480467
if path and not path.endswith('/'):
481468
path += '/'
@@ -494,7 +481,7 @@ def listdir(self, name):
494481
return directories, files
495482

496483
def size(self, name):
497-
name = self._normalize_name(self._clean_name(name))
484+
name = self._normalize_name(clean_name(name))
498485
return self.bucket.Object(name).content_length
499486

500487
def _get_write_parameters(self, name, content=None):
@@ -531,7 +518,7 @@ def get_modified_time(self, name):
531518
Returns an (aware) datetime object containing the last modified time if
532519
USE_TZ is True, otherwise returns a naive datetime in the local timezone.
533520
"""
534-
name = self._normalize_name(self._clean_name(name))
521+
name = self._normalize_name(clean_name(name))
535522
entry = self.bucket.Object(name)
536523
if setting('USE_TZ'):
537524
# boto3 returns TZ aware timestamps
@@ -569,7 +556,7 @@ def _strip_signing_parameters(self, url):
569556

570557
def url(self, name, parameters=None, expire=None, http_method=None):
571558
# Preserve the trailing slash after normalizing the path.
572-
name = self._normalize_name(self._clean_name(name))
559+
name = self._normalize_name(clean_name(name))
573560
params = parameters.copy() if parameters else {}
574561
if expire is None:
575562
expire = self.querystring_expire
@@ -598,7 +585,7 @@ def url(self, name, parameters=None, expire=None, http_method=None):
598585

599586
def get_available_name(self, name, max_length=None):
600587
"""Overwrite existing file with the same name."""
601-
name = self._clean_name(name)
588+
name = clean_name(name)
602589
if self.file_overwrite:
603590
return get_available_overwrite_name(name, max_length)
604591
return super().get_available_name(name, max_length)

tests/test_s3boto3.py

-28
Original file line numberDiff line numberDiff line change
@@ -30,34 +30,6 @@ def setUp(self):
3030
self.storage = s3boto3.S3Boto3Storage()
3131
self.storage._connections.connection = mock.MagicMock()
3232

33-
def test_clean_name(self):
34-
"""
35-
Test the base case of _clean_name
36-
"""
37-
path = self.storage._clean_name("path/to/somewhere")
38-
self.assertEqual(path, "path/to/somewhere")
39-
40-
def test_clean_name_normalize(self):
41-
"""
42-
Test the normalization of _clean_name
43-
"""
44-
path = self.storage._clean_name("path/to/../somewhere")
45-
self.assertEqual(path, "path/somewhere")
46-
47-
def test_clean_name_trailing_slash(self):
48-
"""
49-
Test the _clean_name when the path has a trailing slash
50-
"""
51-
path = self.storage._clean_name("path/to/somewhere/")
52-
self.assertEqual(path, "path/to/somewhere/")
53-
54-
def test_clean_name_windows(self):
55-
"""
56-
Test the _clean_name when the path has a trailing slash
57-
"""
58-
path = self.storage._clean_name("path\\to\\somewhere")
59-
self.assertEqual(path, "path/to/somewhere")
60-
6133
def test_s3_session(self):
6234
settings.AWS_S3_SESSION_PROFILE = "test_profile"
6335
with mock.patch('boto3.Session') as mock_session:

0 commit comments

Comments
 (0)