diff options
author | Mathieu Pillard <mpillard@mozilla.com> | 2022-04-23 12:19:10 +0200 |
---|---|---|
committer | Mathieu Pillard <mpillard@mozilla.com> | 2022-04-23 12:19:10 +0200 |
commit | 2961561b9b8bf43d48d190776db9e097548ab0a5 (patch) | |
tree | 1d9cc8c6aaca13a19e096192ad5f359eba786d1c | |
parent | eadb2f553d131b5bb8fff17dfe38f127b367c616 (diff) | |
parent | 3be5bf6bae72acaca1defcf18c53ac49aadb52cb (diff) | |
download | django-compressor-2961561b9b8bf43d48d190776db9e097548ab0a5.tar.gz |
Merge branch 'develop'4.0
-rw-r--r-- | LICENSE | 86 | ||||
-rw-r--r-- | compressor/__init__.py | 2 | ||||
-rw-r--r-- | compressor/filters/jsmin/__init__.py | 17 | ||||
-rw-r--r-- | compressor/storage.py | 17 | ||||
-rw-r--r-- | compressor/tests/test_filters.py | 3 | ||||
-rw-r--r-- | compressor/tests/test_storages.py | 6 | ||||
-rw-r--r-- | docs/changelog.txt | 10 | ||||
-rw-r--r-- | docs/quickstart.txt | 7 | ||||
-rw-r--r-- | docs/settings.txt | 7 | ||||
-rw-r--r-- | docs/usage.txt | 19 | ||||
-rw-r--r-- | setup.py | 3 |
11 files changed, 65 insertions, 112 deletions
@@ -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>`. @@ -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'), |