Skip to content
This repository has been archived by the owner on Jan 16, 2023. It is now read-only.

Commit

Permalink
fix 151: correctly guess strategy for storage subclasses
Browse files Browse the repository at this point in the history
  • Loading branch information
antonagestam committed Oct 6, 2019
1 parent c6da306 commit 7208faf
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 13 deletions.
2 changes: 1 addition & 1 deletion collectfast/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "1.1.0"
__version__ = "1.1.1"
6 changes: 0 additions & 6 deletions collectfast/management/commands/collectstatic.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import warnings
from multiprocessing.dummy import Pool
from typing import Any
from typing import Dict
Expand Down Expand Up @@ -39,11 +38,6 @@ def _load_strategy():

storage_str = getattr(django_settings, "STATICFILES_STORAGE", None)
if storage_str is not None:
warnings.warn(
"Falling back to guessing strategy for backwards compatibility. This "
"is deprecated and will be removed in a future release. Explicitly "
"set COLLECTFAST_STRATEGY to silence this warning."
)
return load_strategy(guess_strategy(storage_str))

raise ImproperlyConfigured(
Expand Down
43 changes: 37 additions & 6 deletions collectfast/strategies/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import hashlib
import logging
import mimetypes
import warnings
from functools import lru_cache
from io import BytesIO
from pydoc import locate
Expand All @@ -16,6 +17,7 @@
from django.core.exceptions import ImproperlyConfigured
from django.core.files.storage import Storage
from django.utils.encoding import force_bytes
from typing_extensions import Final

from collectfast import settings

Expand Down Expand Up @@ -141,9 +143,38 @@ def load_strategy(klass: Union[str, type, object]) -> Type[Strategy]:
return klass


def guess_strategy(storage: str) -> Optional[str]:
if storage == "storages.backends.s3boto.S3BotoStorage":
return "collectfast.strategies.boto.BotoStrategy"
if storage == "storages.backends.s3boto3.S3Boto3Storage":
return "collectfast.strategies.boto3.Boto3Strategy"
return None
_BOTO_STORAGE = "storages.backends.s3boto.S3BotoStorage" # type: Final
_BOTO_STRATEGY = "collectfast.strategies.boto.BotoStrategy" # type: Final
_BOTO3_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" # type: Final
_BOTO3_STRATEGY = "collectfast.strategies.boto3.Boto3Strategy" # type: Final


def _resolves_to_subclass(subclass_ref: str, superclass_ref: str) -> bool:
subclass = locate(subclass_ref)
assert isinstance(subclass, type)
try:
superclass = locate(superclass_ref)
assert isinstance(superclass, type)
except (ImportError, AssertionError) as e:
logger.debug("Failed to import %s: %s" % (superclass_ref, e))
return False
return issubclass(subclass, superclass)


def guess_strategy(storage: str) -> str:
warnings.warn(
"Falling back to guessing strategy for backwards compatibility. This "
"is deprecated and will be removed in a future release. Explicitly "
"set COLLECTFAST_STRATEGY to silence this warning."
)
if storage == _BOTO_STORAGE:
return _BOTO_STRATEGY
if storage == _BOTO3_STORAGE:
return _BOTO3_STRATEGY
if _resolves_to_subclass(storage, _BOTO_STORAGE):
return _BOTO_STRATEGY
if _resolves_to_subclass(storage, _BOTO3_STORAGE):
return _BOTO3_STRATEGY
raise ImproperlyConfigured(
"No strategy configured, please make sure COLLECTFAST_STRATEGY is set."
)
5 changes: 5 additions & 0 deletions collectfast/tests/boto3_subclass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from storages.backends.s3boto3 import S3Boto3Storage


class CustomStorage(S3Boto3Storage):
pass
5 changes: 5 additions & 0 deletions collectfast/tests/boto_subclass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from storages.backends.s3boto import S3BotoStorage


class CustomStorage(S3BotoStorage):
pass
37 changes: 37 additions & 0 deletions collectfast/tests/strategies/test_guess_strategy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from unittest import TestCase

from collectfast.strategies.base import _BOTO3_STORAGE
from collectfast.strategies.base import _BOTO3_STRATEGY
from collectfast.strategies.base import _BOTO_STORAGE
from collectfast.strategies.base import _BOTO_STRATEGY
from collectfast.strategies.base import guess_strategy
from collectfast.tests.utils import test


@test
def test_guesses_boto_from_exact(case):
# type: (TestCase) -> None
case.assertEqual(guess_strategy(_BOTO_STORAGE), _BOTO_STRATEGY)


@test
def test_guesses_boto3_from_exact(case):
# type: (TestCase) -> None
case.assertEqual(guess_strategy(_BOTO3_STORAGE), _BOTO3_STRATEGY)


@test
def test_guesses_boto_from_subclass(case):
# type: (TestCase) -> None
case.assertEqual(
guess_strategy("collectfast.tests.boto_subclass.CustomStorage"), _BOTO_STRATEGY
)


@test
def test_guesses_boto3_from_subclass(case):
# type: (TestCase) -> None
case.assertEqual(
guess_strategy("collectfast.tests.boto3_subclass.CustomStorage"),
_BOTO3_STRATEGY,
)

0 comments on commit 7208faf

Please sign in to comment.