#35868: 'collectstatic' management command inappropriately eating AttributeError
exceptions
-------------------------------------+-------------------------------------
Reporter: Brett G | Owner: (none)
Type: Bug | Status: new
Component: contrib.staticfiles | Version: 5.0
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------
Description changed by Brett G:
Old description:
> Recently, Django 5.0 [https://docs.djangoproject.com/en/5.1/releases/5.0
> /#features-removed-in-5-0 removed] the `django.utils.timezone.utc` alias
> to `datetime.timezone.utc`.
>
> I've written a custom file storage class that implements a
> `get_modified_time` method which, predictably, used the
> `django.utils.timezone.utc` alias.
>
> The code in
> 'django/contrib/staticfiles/management/commands/collectstatic.py' reads
> as follows:
>
> {{{#!python
> try:
> # When was the target file modified last time?
> target_last_modified =
> self.storage.get_modified_time(prefixed_path)
> except (OSError, NotImplementedError, AttributeError):
> # The storage doesn't support get_modified_time() or
> failed
> pass
> else:
> try:
> # When was the source file modified last time?
> source_last_modified =
> source_storage.get_modified_time(path)
> except (OSError, NotImplementedError, AttributeError):
> pass
> }}}
>
> I assume the exception catch there is meant to ignore `AttributeError`
> exceptions from custom file storage classes that do not implement
> `get_modified_time`. This is inappropriate - custom file storage classes
> can be written by users, and the `get_modified_time` method may raise
> `AttributeError` for a completely unrelated reason.
>
> The net effect of this is that when `collectstatic` was run, ''all''
> static files were copied, regardless of modification time, as
> `collectstatic` silently ignored this error. This was difficult to pin
> down.
>
> Checking for the presence of a `get_modified_time` attribute using duck
> typing (eg. `hasattr(self.storage, 'get_modified_time')`) may be more
> appropriate than eating such a generic exception.
New description:
Recently, Django 5.0 [https://docs.djangoproject.com/en/5.1/releases/5.0
/#features-removed-in-5-0 removed] the `django.utils.timezone.utc` alias
to `datetime.timezone.utc`.
I've written a custom file storage class that implements a
`get_modified_time` method which, predictably, used the
`django.utils.timezone.utc` alias. Use of this alias raises an
`AttributeError` in Django 5.0.
The code in
'django/contrib/staticfiles/management/commands/collectstatic.py' reads as
follows:
{{{#!python
try:
# When was the target file modified last time?
target_last_modified =
self.storage.get_modified_time(prefixed_path)
except (OSError, NotImplementedError, AttributeError):
# The storage doesn't support get_modified_time() or
failed
pass
else:
try:
# When was the source file modified last time?
source_last_modified =
source_storage.get_modified_time(path)
except (OSError, NotImplementedError, AttributeError):
pass
}}}
I assume the exception catch there is meant to ignore `AttributeError`
exceptions from custom file storage classes that do not implement
`get_modified_time`. This is inappropriate - custom file storage classes
can be written by users, and the `get_modified_time` method may raise
`AttributeError` for a completely unrelated reason.
The net effect of this is that due to the `AttributeError` raised by my
own `get_modified_time` method, when `collectstatic` was run, ''all''
static files were copied, regardless of modification time, as
`collectstatic` silently ignored this error. This was difficult to pin
down.
Checking for the presence of a `get_modified_time` attribute using duck
typing (eg. `hasattr(self.storage, 'get_modified_time')`) may be more
appropriate than eating such a generic exception.
--
--
Ticket URL: <https://code.djangoproject.com/ticket/35868#comment:1>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/django-updates/01070192cb598587-a076465f-6f3d-4299-8069-7e1bd5bc9f7f-000000%40eu-central-1.amazonses.com.