def test_css_hunks(self): hash_dict = { 'hash1': get_hashed_mtime(os.path.join(settings.COMPRESS_ROOT, 'css/url/url1.css')), 'hash2': get_hashed_mtime(os.path.join(settings.COMPRESS_ROOT, 'css/url/2/url2.css')), } out = [u"p { background: url('/media/images/test.png?%(hash1)s'); }\np { background: url('/media/images/test.png?%(hash1)s'); }\np { background: url('/media/images/test.png?%(hash1)s'); }\np { background: url('/media/images/test.png?%(hash1)s'); }\n" % hash_dict, u"p { background: url('/media/images/test.png?%(hash2)s'); }\np { background: url('/media/images/test.png?%(hash2)s'); }\np { background: url('/media/images/test.png?%(hash2)s'); }\np { background: url('/media/images/test.png?%(hash2)s'); }\n" % hash_dict] self.assertEqual(out, list(self.css_node.hunks))
def test_css_absolute_filter_relative_path(self): from compressor.filters.css_default import CssAbsoluteFilter filename = os.path.join(settings.TEST_DIR, 'whatever', '..', 'media', 'whatever/../css/url/test.css') content = "p { background: url('../../images/image.gif') }" output = "p { background: url('%simages/image.gif?%s') }" % ( settings.COMPRESS_URL, get_hashed_mtime(filename)) filter = CssAbsoluteFilter(content) self.assertEqual(output, filter.input(filename=filename)) settings.COMPRESS_URL = 'https://media.example.com/' output = "p { background: url('%simages/image.gif?%s') }" % ( settings.COMPRESS_URL, get_hashed_mtime(filename)) self.assertEqual(output, filter.input(filename=filename))
def input(self, filename=None, **kwargs): self.root = os.path.normcase(os.path.abspath(settings.COMPRESS_ROOT)) if filename is not None: filename = os.path.normcase(os.path.abspath(filename)) if not filename or not filename.startswith(self.root): return self.content self.path = filename[len(self.root):].replace(os.sep, '/') self.path = self.path.lstrip('/') self.url = settings.COMPRESS_URL.rstrip('/') self.url_path = self.url try: self.mtime = get_hashed_mtime(filename) except OSError: self.mtime = None self.has_http = False if self.url.startswith('http://') or self.url.startswith('https://'): self.has_http = True parts = self.url.split('/') self.url = '/'.join(parts[2:]) self.url_path = '/%s' % '/'.join(parts[3:]) self.protocol = '%s/' % '/'.join(parts[:2]) self.host = parts[2] self.directory_name = '/'.join([self.url, os.path.dirname(self.path)]) output = URL_PATTERN.sub(self.url_converter, self.content) return output
def add_suffix(self, url): filename = self.guess_filename(url) if not filename: return url if settings.COMPRESS_CSS_HASHING_METHOD is None: return url if not url.startswith(SCHEMES): return url suffix = None if settings.COMPRESS_CSS_HASHING_METHOD == "mtime": suffix = get_hashed_mtime(filename) elif settings.COMPRESS_CSS_HASHING_METHOD in ("hash", "content"): suffix = get_hashed_content(filename) else: raise FilterError('COMPRESS_CSS_HASHING_METHOD is configured ' 'with an unknown method (%s).' % settings.COMPRESS_CSS_HASHING_METHOD) fragment = None if "#" in url: url, fragment = url.rsplit("#", 1) if "?" in url: url = "%s&%s" % (url, suffix) else: url = "%s?%s" % (url, suffix) if fragment is not None: url = "%s#%s" % (url, fragment) return url
def test_data_uris(self): datauri_hash = get_hashed_mtime( os.path.join(settings.COMPRESS_ROOT, 'css/datauri.css')) out = [ u'.add { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJvSURBVDjLpZPrS5NhGIf9W7YvBYOkhlkoqCklWChv2WyKik7blnNris72bi6dus0DLZ0TDxW1odtopDs4D8MDZuLU0kXq61CijSIIasOvv94VTUfLiB74fXngup7nvrnvJABJ/5PfLnTTdcwOj4RsdYmo5glBWP6iOtzwvIKSWstI0Wgx80SBblpKtE9KQs/We7EaWoT/8wbWP61gMmCH0lMDvokT4j25TiQU/ITFkek9Ow6+7WH2gwsmahCPdwyw75uw9HEO2gUZSkfyI9zBPCJOoJ2SMmg46N61YO/rNoa39Xi41oFuXysMfh36/Fp0b7bAfWAH6RGi0HglWNCbzYgJaFjRv6zGuy+b9It96N3SQvNKiV9HvSaDfFEIxXItnPs23BzJQd6DDEVM0OKsoVwBG/1VMzpXVWhbkUM2K4oJBDYuGmbKIJ0qxsAbHfRLzbjcnUbFBIpx/qH3vQv9b3U03IQ/HfFkERTzfFj8w8jSpR7GBE123uFEYAzaDRIqX/2JAtJbDat/COkd7CNBva2cMvq0MGxp0PRSCPF8BXjWG3FgNHc9XPT71Ojy3sMFdfJRCeKxEsVtKwFHwALZfCUk3tIfNR8XiJwc1LmL4dg141JPKtj3WUdNFJqLGFVPC4OkR4BxajTWsChY64wmCnMxsWPCHcutKBxMVp5mxA1S+aMComToaqTRUQknLTH62kHOVEE+VQnjahscNCy0cMBWsSI0TCQcZc5ALkEYckL5A5noWSBhfm2AecMAjbcRWV0pUTh0HE64TNf0mczcnnQyu/MilaFJCae1nw2fbz1DnVOxyGTlKeZft/Ff8x1BRssfACjTwQAAAABJRU5ErkJggg=="); }\n.python { background-image: url("/media/img/python.png?%s"); }\n.datauri { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9YGARc5KB0XV+IAAAAddEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q72QlbgAAAF1JREFUGNO9zL0NglAAxPEfdLTs4BZM4DIO4C7OwQg2JoQ9LE1exdlYvBBeZ7jqch9//q1uH4TLzw4d6+ErXMMcXuHWxId3KOETnnXXV6MJpcq2MLaI97CER3N0 vr4MkhoXe0rZigAAAABJRU5ErkJggg=="); }\n' % datauri_hash ] self.assertEqual(out, list(self.css_node.hunks))
def test_data_uris(self): datauri_hash = get_hashed_mtime(os.path.join(settings.COMPRESS_ROOT, 'img/python.png')) out = [u'''.add { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJvSURBVDjLpZPrS5NhGIf9W7YvBYOkhlkoqCklWChv2WyKik7blnNris72bi6dus0DLZ0TDxW1odtopDs4D8MDZuLU0kXq61CijSIIasOvv94VTUfLiB74fXngup7nvrnvJABJ/5PfLnTTdcwOj4RsdYmo5glBWP6iOtzwvIKSWstI0Wgx80SBblpKtE9KQs/We7EaWoT/8wbWP61gMmCH0lMDvokT4j25TiQU/ITFkek9Ow6+7WH2gwsmahCPdwyw75uw9HEO2gUZSkfyI9zBPCJOoJ2SMmg46N61YO/rNoa39Xi41oFuXysMfh36/Fp0b7bAfWAH6RGi0HglWNCbzYgJaFjRv6zGuy+b9It96N3SQvNKiV9HvSaDfFEIxXItnPs23BzJQd6DDEVM0OKsoVwBG/1VMzpXVWhbkUM2K4oJBDYuGmbKIJ0qxsAbHfRLzbjcnUbFBIpx/qH3vQv9b3U03IQ/HfFkERTzfFj8w8jSpR7GBE123uFEYAzaDRIqX/2JAtJbDat/COkd7CNBva2cMvq0MGxp0PRSCPF8BXjWG3FgNHc9XPT71Ojy3sMFdfJRCeKxEsVtKwFHwALZfCUk3tIfNR8XiJwc1LmL4dg141JPKtj3WUdNFJqLGFVPC4OkR4BxajTWsChY64wmCnMxsWPCHcutKBxMVp5mxA1S+aMComToaqTRUQknLTH62kHOVEE+VQnjahscNCy0cMBWsSI0TCQcZc5ALkEYckL5A5noWSBhfm2AecMAjbcRWV0pUTh0HE64TNf0mczcnnQyu/MilaFJCae1nw2fbz1DnVOxyGTlKeZft/Ff8x1BRssfACjTwQAAAABJRU5ErkJggg=="); } .add-with-hash { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJvSURBVDjLpZPrS5NhGIf9W7YvBYOkhlkoqCklWChv2WyKik7blnNris72bi6dus0DLZ0TDxW1odtopDs4D8MDZuLU0kXq61CijSIIasOvv94VTUfLiB74fXngup7nvrnvJABJ/5PfLnTTdcwOj4RsdYmo5glBWP6iOtzwvIKSWstI0Wgx80SBblpKtE9KQs/We7EaWoT/8wbWP61gMmCH0lMDvokT4j25TiQU/ITFkek9Ow6+7WH2gwsmahCPdwyw75uw9HEO2gUZSkfyI9zBPCJOoJ2SMmg46N61YO/rNoa39Xi41oFuXysMfh36/Fp0b7bAfWAH6RGi0HglWNCbzYgJaFjRv6zGuy+b9It96N3SQvNKiV9HvSaDfFEIxXItnPs23BzJQd6DDEVM0OKsoVwBG/1VMzpXVWhbkUM2K4oJBDYuGmbKIJ0qxsAbHfRLzbjcnUbFBIpx/qH3vQv9b3U03IQ/HfFkERTzfFj8w8jSpR7GBE123uFEYAzaDRIqX/2JAtJbDat/COkd7CNBva2cMvq0MGxp0PRSCPF8BXjWG3FgNHc9XPT71Ojy3sMFdfJRCeKxEsVtKwFHwALZfCUk3tIfNR8XiJwc1LmL4dg141JPKtj3WUdNFJqLGFVPC4OkR4BxajTWsChY64wmCnMxsWPCHcutKBxMVp5mxA1S+aMComToaqTRUQknLTH62kHOVEE+VQnjahscNCy0cMBWsSI0TCQcZc5ALkEYckL5A5noWSBhfm2AecMAjbcRWV0pUTh0HE64TNf0mczcnnQyu/MilaFJCae1nw2fbz1DnVOxyGTlKeZft/Ff8x1BRssfACjTwQAAAABJRU5ErkJggg=="); } .python { background-image: url("/media/img/python.png?%s"); } .datauri { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9YGARc5KB0XV+IAAAAddEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q72QlbgAAAF1JREFUGNO9zL0NglAAxPEfdLTs4BZM4DIO4C7OwQg2JoQ9LE1exdlYvBBeZ7jqch9//q1uH4TLzw4d6+ErXMMcXuHWxId3KOETnnXXV6MJpcq2MLaI97CER3N0 vr4MkhoXe0rZigAAAABJRU5ErkJggg=="); } ''' % datauri_hash] self.assertEqual(out, list(self.css_node.hunks()))
def test_css_absolute_filter_https(self): from compressor.filters.css_default import CssAbsoluteFilter filename = os.path.join(settings.COMPRESS_ROOT, 'css/url/test.css') content = "p { background: url('../../images/image.gif') }" output = "p { background: url('%simages/image.gif?%s') }" % ( settings.COMPRESS_URL, get_hashed_mtime(filename)) filter = CssAbsoluteFilter(content) self.assertEqual( output, filter.input(filename=filename, basename='css/url/test.css')) settings.COMPRESS_URL = 'https://media.example.com/' filename = os.path.join(settings.COMPRESS_ROOT, 'css/url/test.css') output = "p { background: url('%simages/image.gif?%s') }" % ( settings.COMPRESS_URL, get_hashed_mtime(filename)) self.assertEqual( output, filter.input(filename=filename, basename='css/url/test.css'))
def add_mtime(self, url): filename = self.guess_filename(url) mtime = filename and get_hashed_mtime(filename) or self.mtime if mtime is None: return url if url.startswith(('http://', 'https://', '/')): if "?" in url: url = "%s&%s" % (url, mtime) else: url = "%s?%s" % (url, mtime) return url
def input(self, filename=None, basename=None, **kwargs): if filename is not None: filename = os.path.normcase(os.path.abspath(filename)) if (not (filename and filename.startswith(self.root)) and not self.find(basename)): return self.content self.path = basename.replace(os.sep, '/') self.path = self.path.lstrip('/') self.mtime = get_hashed_mtime(filename) if self.url.startswith(('http://', 'https://')): self.has_scheme = True parts = self.url.split('/') self.url = '/'.join(parts[2:]) self.url_path = '/%s' % '/'.join(parts[3:]) self.protocol = '%s/' % '/'.join(parts[:2]) self.host = parts[2] self.directory_name = '/'.join((self.url, os.path.dirname(self.path))) return URL_PATTERN.sub(self.url_converter, self.content)
def add_suffix(self, url): filename = self.guess_filename(url) suffix = None if filename: if settings.COMPRESS_CSS_HASHING_METHOD == "mtime": suffix = get_hashed_mtime(filename) elif settings.COMPRESS_CSS_HASHING_METHOD in ("hash", "content"): suffix = get_hashed_content(filename) else: raise FilterError('COMPRESS_CSS_HASHING_METHOD is configured ' 'with an unknown method (%s).') if suffix is None: return url if url.startswith(('http://', 'https://', '/')): if "?" in url: url = "%s&%s" % (url, suffix) else: url = "%s?%s" % (url, suffix) return url
def add_suffix(self, url): filename = self.guess_filename(url) suffix = None if filename: if settings.COMPRESS_CSS_HASHING_METHOD == "mtime": suffix = get_hashed_mtime(filename) elif settings.COMPRESS_CSS_HASHING_METHOD == "hash": hash_file = open(filename) try: suffix = get_hexdigest(hash_file.read(), 12) finally: hash_file.close() else: raise FilterError('COMPRESS_CSS_HASHING_METHOD is configured ' 'with an unknown method (%s).') if suffix is None: return url if url.startswith(('http://', 'https://', '/')): if "?" in url: url = "%s&%s" % (url, suffix) else: url = "%s?%s" % (url, suffix) return url
def test_css_absolute_filter_relative_path(self): from compressor.filters.css_default import CssAbsoluteFilter filename = os.path.join(settings.TEST_DIR, 'whatever', '..', 'media', 'whatever/../css/url/test.css') content = "p { background: url('../../images/image.gif') }" output = "p { background: url('%simages/image.gif?%s') }" % (settings.COMPRESS_URL, get_hashed_mtime(filename)) filter = CssAbsoluteFilter(content) self.assertEqual(output, filter.input(filename=filename, basename='css/url/test.css')) settings.COMPRESS_URL = 'https://media.example.com/' filter = CssAbsoluteFilter(content) output = "p { background: url('%simages/image.gif?%s') }" % (settings.COMPRESS_URL, get_hashed_mtime(filename)) self.assertEqual(output, filter.input(filename=filename, basename='css/url/test.css'))
def suffix_method(self, filename): return get_hashed_mtime(filename)
def test_css_absolute_filter(self): from compressor.filters.css_default import CssAbsoluteFilter filename = os.path.join(settings.COMPRESS_ROOT, 'css/url/test.css') content = "p { background: url('../../images/image.gif') }" output = "p { background: url('%simages/image.gif?%s') }" % (settings.COMPRESS_URL, get_hashed_mtime(filename)) filter = CssAbsoluteFilter(content) self.assertEqual(output, filter.input(filename=filename)) settings.COMPRESS_URL = 'http://media.example.com/' filename = os.path.join(settings.COMPRESS_ROOT, 'css/url/test.css') output = "p { background: url('%simages/image.gif?%s') }" % (settings.COMPRESS_URL, get_hashed_mtime(filename)) self.assertEqual(output, filter.input(filename=filename))