summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathieu Pillard <mpillard@mozilla.com>2022-04-23 12:19:10 +0200
committerMathieu Pillard <mpillard@mozilla.com>2022-04-23 12:19:10 +0200
commit2961561b9b8bf43d48d190776db9e097548ab0a5 (patch)
tree1d9cc8c6aaca13a19e096192ad5f359eba786d1c
parenteadb2f553d131b5bb8fff17dfe38f127b367c616 (diff)
parent3be5bf6bae72acaca1defcf18c53ac49aadb52cb (diff)
downloaddjango-compressor-2961561b9b8bf43d48d190776db9e097548ab0a5.tar.gz
Merge branch 'develop'4.0
-rw-r--r--LICENSE86
-rw-r--r--compressor/__init__.py2
-rw-r--r--compressor/filters/jsmin/__init__.py17
-rw-r--r--compressor/storage.py17
-rw-r--r--compressor/tests/test_filters.py3
-rw-r--r--compressor/tests/test_storages.py6
-rw-r--r--docs/changelog.txt10
-rw-r--r--docs/quickstart.txt7
-rw-r--r--docs/settings.txt7
-rw-r--r--docs/usage.txt19
-rw-r--r--setup.py3
11 files changed, 65 insertions, 112 deletions
diff --git a/LICENSE b/LICENSE
index 43f0933..c7b457b 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
django_compressor
-----------------
-Copyright (c) 2009-2015 Django Compressor authors (see AUTHORS file)
+Copyright (c) 2009-2022 Django Compressor authors (see AUTHORS file)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -42,87 +42,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-
-
-rjsmin.py (License-information from the file)
----------------------------------------------
-Copyright 2006, 2007, 2008, 2009, 2010, 2011
-André Malo or his licensors, as applicable
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-
-utils.cache.cached_property extracted from Celery
--------------------------------------------
-Copyright (c) 2009-2011, Ask Solem and contributors.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-Neither the name of Ask Solem nor the names of its contributors may be used
-to endorse or promote products derived from this software without specific
-prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
-utils.FormattableString
------------------------
-Copyright (c) 2010 by Florent Xicluna.
-
-Some rights reserved.
-
-Redistribution and use in source and binary forms of the software as well
-as documentation, with or without modification, are permitted provided
-that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials provided
- with the distribution.
-
-* The names of the contributors may not be used to endorse or
- promote products derived from this software without specific
- prior written permission.
-
-THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND
-CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
-NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGE.
diff --git a/compressor/__init__.py b/compressor/__init__.py
index a4702e2..7f21c2d 100644
--- a/compressor/__init__.py
+++ b/compressor/__init__.py
@@ -1,2 +1,2 @@
# following PEP 386
-__version__ = "3.1"
+__version__ = "4.0"
diff --git a/compressor/filters/jsmin/__init__.py b/compressor/filters/jsmin/__init__.py
index 3a2aade..c1a64cf 100644
--- a/compressor/filters/jsmin/__init__.py
+++ b/compressor/filters/jsmin/__init__.py
@@ -1,3 +1,5 @@
+import warnings
+
from django.core.exceptions import ImproperlyConfigured
from compressor.filters import FilterBase, CallbackOutputFilter
@@ -6,9 +8,7 @@ from compressor.filters import FilterBase, CallbackOutputFilter
class rJSMinFilter(CallbackOutputFilter):
callback = "rjsmin.jsmin"
dependencies = ["rjsmin"]
- kwargs = {
- "keep_bang_comments": True
- }
+ kwargs = {"keep_bang_comments": True}
# This is for backwards compatibility
@@ -22,6 +22,14 @@ class SlimItFilter(CallbackOutputFilter):
"mangle": True,
}
+ def __init__(self, *args, **kwargs):
+ warnings.warn(
+ "SlimItFilter is broken in Python 3.6+ and will be removed in "
+ "django-compressor 3.3.",
+ DeprecationWarning,
+ )
+ super().__init__(*args, **kwargs)
+
class CalmjsFilter(FilterBase):
def __init__(self, *args, **kwargs):
@@ -39,7 +47,8 @@ class CalmjsFilter(FilterBase):
except ImportError:
raise ImproperlyConfigured(
"The module calmjs.parse couldn't be imported. "
- "Make sure it is correctly installed.")
+ "Make sure it is correctly installed."
+ )
if self._parser is None:
self._parser = calmjs.parse.es5
if self._unparser is None:
diff --git a/compressor/storage.py b/compressor/storage.py
index a9d7a0c..5d12eb8 100644
--- a/compressor/storage.py
+++ b/compressor/storage.py
@@ -33,13 +33,16 @@ class CompressorFileStorage(FileSystemStorage):
def modified_time(self, name):
return datetime.fromtimestamp(os.path.getmtime(self.path(name)))
- def get_available_name(self, name, max_length=None):
- """
- Deletes the given file if it exists.
- """
- if self.exists(name):
- self.delete(name)
- return name
+ def save(self, filename, content):
+ temp_filename = super().save(filename, content)
+ # If a file already exists in the target location, FileSystemStorage
+ # will generate an unique filename and save content there instead.
+ # When that happens, we move the file to the intended location using
+ # os.replace() (which is an atomic operation):
+ if temp_filename != filename:
+ os.replace(self.path(temp_filename), self.path(filename))
+
+ return filename
compressor_file_storage = SimpleLazyObject(
diff --git a/compressor/tests/test_filters.py b/compressor/tests/test_filters.py
index 49716b7..ddcfab0 100644
--- a/compressor/tests/test_filters.py
+++ b/compressor/tests/test_filters.py
@@ -2,7 +2,7 @@ import io
import os
import sys
from collections import defaultdict
-from unittest import mock
+from unittest import mock, skipIf
from django.conf import settings
from django.test import override_settings, TestCase
@@ -202,6 +202,7 @@ class JsMinTestCase(TestCase):
self.assertEqual(output, rJSMinFilter(content).output())
+@skipIf(sys.version_info >= (3, 7), reason="Unsupported in Python 3.7+")
class SlimItTestCase(TestCase):
def test_slimit_filter(self):
content = """
diff --git a/compressor/tests/test_storages.py b/compressor/tests/test_storages.py
index 8a99e45..9168510 100644
--- a/compressor/tests/test_storages.py
+++ b/compressor/tests/test_storages.py
@@ -61,3 +61,9 @@ class StorageTestCase(TestCase):
context = {'STATIC_URL': settings.COMPRESS_URL}
out = css_tag("/static/CACHE/css/output.e701f86c6430.css")
self.assertEqual(out, render(template, context))
+
+ def test_duplicate_save_overwrites_same_file(self):
+ filename1 = self.default_storage.save('test.txt', ContentFile('yeah yeah'))
+ filename2 = self.default_storage.save('test.txt', ContentFile('yeah yeah'))
+ self.assertEqual(filename1, filename2)
+ self.assertNotIn("_", filename2)
diff --git a/docs/changelog.txt b/docs/changelog.txt
index 3d19a44..0f1a447 100644
--- a/docs/changelog.txt
+++ b/docs/changelog.txt
@@ -1,6 +1,16 @@
Changelog
=========
+v4.0 (2022-03-23)
+-----------------
+
+`Full Changelog <https://github.com/django-compressor/django-compressor/compare/3.1...4.0>`_
+
+- Fix intermittent No such file or directory errors by changing strategy to
+ deal with duplicate filenames in CompressorFileStorage
+- Deprecate SlimItFilter, stop testing it with Python 3.7 or higher
+
+
v3.1 (2021-12-18)
-----------------
diff --git a/docs/quickstart.txt b/docs/quickstart.txt
index 86d09c2..f6f23a4 100644
--- a/docs/quickstart.txt
+++ b/docs/quickstart.txt
@@ -64,13 +64,6 @@ Optional Dependencies
pip install html5lib
-- `Slim It`_
-
- For the :ref:`Slim It filter <slimit_filter>`
- ``compressor.filters.jsmin.SlimItFilter``::
-
- pip install slimit
-
- `Calmjs`_
For the :ref:`Calmjs filter <calmjs_filter>`
diff --git a/docs/settings.txt b/docs/settings.txt
index b164ad8..7b65b66 100644
--- a/docs/settings.txt
+++ b/docs/settings.txt
@@ -201,13 +201,6 @@ Backend settings
A filter that uses the jsmin implementation rJSmin_ to compress
JavaScript code (installed by default).
- .. _slimit_filter:
-
- - ``compressor.filters.jsmin.SlimItFilter``
-
- A filter that uses the jsmin implementation `Slim It`_ to compress
- JavaScript code.
-
.. _calmjs_filter:
- ``compressor.filters.jsmin.CalmjsFilter``
diff --git a/docs/usage.txt b/docs/usage.txt
index ac572c7..f038668 100644
--- a/docs/usage.txt
+++ b/docs/usage.txt
@@ -79,6 +79,25 @@ Result:
<script type="text/javascript" src="/static/CACHE/js/base.3f33b9146e12.js" charset="utf-8"></script>
+Javascript ``async`` and ``defer`` are supported:
+
+ .. code-block:: django
+
+ {% compress js %}
+ <script src="/static/js/one.js" async></script>
+ {% endcompress %}
+ {% compress js %}
+ <script src="/static/js/one.js" defer></script>
+ {% endcompress %}
+
+Result:
+
+ .. code-block:: django
+
+ <script async src="/static/CACHE/js/output.ccbb802fbf33.js"></script>
+ <script defer src="/static/CACHE/js/output.5bd495b0eb05.js"></script>
+
+
.. note::
Remember that django-compressor will try to :ref:`group outputs by media <css_notes>`.
diff --git a/setup.py b/setup.py
index d8806de..f9558a9 100644
--- a/setup.py
+++ b/setup.py
@@ -117,6 +117,9 @@ setup(
name="django_compressor",
version=find_version("compressor", "__init__.py"),
url='https://django-compressor.readthedocs.io/en/latest/',
+ project_urls={
+ 'Source': 'https://github.com/django-compressor/django-compressor',
+ },
license='MIT',
description="Compresses linked and inline JavaScript or CSS into single cached files.",
long_description=read('README.rst'),