Commit 5e6a6739 by Timothée Peignier

merge with master

parents 66831255 21de7a6c
...@@ -14,4 +14,5 @@ tests/static/ ...@@ -14,4 +14,5 @@ tests/static/
tests/assets/js/dummy.js tests/assets/js/dummy.js
.tox/ .tox/
.DS_Store .DS_Store
.idea .idea
\ No newline at end of file .venv
\ No newline at end of file
...@@ -25,6 +25,8 @@ or just made Pipeline more awesome. ...@@ -25,6 +25,8 @@ or just made Pipeline more awesome.
* Casey Greene <csgreene@princeton.edu> * Casey Greene <csgreene@princeton.edu>
* Christian Hammond <chipx86@chipx86.com> * Christian Hammond <chipx86@chipx86.com>
* David Charbonnier <d.charbonnier@oxys.net> * David Charbonnier <d.charbonnier@oxys.net>
* Adam Charnock <adam@omniwiki.co.uk>
* Balazs Kossovics <balazs.kossovics@e-loue.com>
* Timothée Peignier <timothee.peignier@tryphon.org> * Timothée Peignier <timothee.peignier@tryphon.org>
The python version of jsmin (http://www.crockford.com/javascript/jsmin.html) The python version of jsmin (http://www.crockford.com/javascript/jsmin.html)
......
Pipeline Pipeline
-------- --------
Copyright (c) 2008 Andreas Pelme <andreas@pelme.se> Copyright (©) 2008 Andreas Pelme <andreas@pelme.se>
Copyright (c) 2011 Timothée Peignier <timothee.peignier@tryphon.org> Copyright (©) 2011-2012 Timothée Peignier <timothee.peignier@tryphon.org>
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
...@@ -27,10 +27,7 @@ This code is original from jsmin by Douglas Crockford, it was translated to ...@@ -27,10 +27,7 @@ This code is original from jsmin by Douglas Crockford, it was translated to
Python by Baruch Even. The original code had the following copyright and Python by Baruch Even. The original code had the following copyright and
license. license.
/* jsmin.c Copyright (©) 2002 Douglas Crockford (www.crockford.com)
2007-05-22
Copyright (c) 2002 Douglas Crockford (www.crockford.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in
...@@ -50,5 +47,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ...@@ -50,5 +47,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ \ No newline at end of file
Pipeline Pipeline
======== ========
Pipeline is an asset packaging library for Django, providing both CSS and JavaScript concatenation and compression, built-in JavaScript template support, and optional data-URI image embedding. Pipeline is an asset packaging library for Django, providing both CSS and JavaScript concatenation and compression, built-in JavaScript template support, and optional data-URI image and font embedding.
To install it : To install it :
......
...@@ -3,4 +3,3 @@ Changelog ...@@ -3,4 +3,3 @@ Changelog
1.2.0 1.2.0
----- -----
...@@ -41,7 +41,7 @@ master_doc = 'index' ...@@ -41,7 +41,7 @@ master_doc = 'index'
# General information about the project. # General information about the project.
project = u'django-pipeline' project = u'django-pipeline'
copyright = u'2011, Timothée Peignier' copyright = u'2011-2012, Timothée Peignier'
# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the # |version| and |release|, also used in various other places throughout the
......
...@@ -7,7 +7,7 @@ from itertools import takewhile ...@@ -7,7 +7,7 @@ from itertools import takewhile
from pipeline.conf import settings from pipeline.conf import settings
from pipeline.storage import storage from pipeline.storage import storage
from pipeline.utils import to_class, relpath from pipeline.utils import filepath_to_uri, to_class, relpath
MAX_IMAGE_SIZE = 32700 MAX_IMAGE_SIZE = 32700
...@@ -117,7 +117,7 @@ class Compressor(object): ...@@ -117,7 +117,7 @@ class Compressor(object):
path = os.path.basename(path) path = os.path.basename(path)
if path == base: if path == base:
base = os.path.dirname(path) base = os.path.dirname(path)
name = re.sub(r"^%s\/?(.*)%s$" % ( name = re.sub(r"^%s[\/\\]?(.*)%s$" % (
re.escape(base), re.escape(settings.PIPELINE_TEMPLATE_EXT) re.escape(base), re.escape(settings.PIPELINE_TEMPLATE_EXT)
), r"\1", path) ), r"\1", path)
return re.sub(r"[\/\\]", "_", name) return re.sub(r"[\/\\]", "_", name)
......
import os from django.core.files import temp as tempfile
import tempfile
from pipeline.conf import settings from pipeline.conf import settings
from pipeline.compressors import SubProcessCompressor from pipeline.compressors import SubProcessCompressor
...@@ -7,18 +6,15 @@ from pipeline.compressors import SubProcessCompressor ...@@ -7,18 +6,15 @@ from pipeline.compressors import SubProcessCompressor
class CSSTidyCompressor(SubProcessCompressor): class CSSTidyCompressor(SubProcessCompressor):
def compress_css(self, css): def compress_css(self, css):
out_file, out_filename = tempfile.mkstemp() output_file = tempfile.NamedTemporaryFile(suffix='.pipeline')
out_file = os.fdopen(out_file, 'rb')
command = '%s - %s %s' % ( command = '%s - %s %s' % (
settings.PIPELINE_CSSTIDY_BINARY, settings.PIPELINE_CSSTIDY_BINARY,
settings.PIPELINE_CSSTIDY_ARGUMENTS, settings.PIPELINE_CSSTIDY_ARGUMENTS,
out_filename output_file.name
) )
self.execute_command(command, css) self.execute_command(command, css)
filtered_css = out_file.read() filtered_css = output_file.read()
out_file.close() output_file.close()
os.remove(out_filename)
return filtered_css return filtered_css
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from django.utils.encoding import smart_str
from pipeline.conf import settings from pipeline.conf import settings
from pipeline.compilers import Compiler from pipeline.compilers import Compiler
...@@ -112,7 +113,7 @@ class Packager(object): ...@@ -112,7 +113,7 @@ class Packager(object):
return self.compressor.compile_templates(package.templates) return self.compressor.compile_templates(package.templates)
def save_file(self, path, content): def save_file(self, path, content):
return storage.save(path, ContentFile(content)) return storage.save(path, ContentFile(smart_str(content)))
def create_packages(self, config): def create_packages(self, config):
packages = {} packages = {}
......
import os import os
import sys import sys
import urllib
from django.utils import importlib from django.utils import importlib
from django.utils.encoding import smart_str
def to_class(class_str): def to_class(class_str):
...@@ -14,6 +16,12 @@ def to_class(class_str): ...@@ -14,6 +16,12 @@ def to_class(class_str):
return getattr(module, class_name, None) return getattr(module, class_name, None)
def filepath_to_uri(path):
if path is None:
return path
return urllib.quote(smart_str(path).replace("\\", "/"), safe="/~!*()'#?")
def _relpath_nt(path, start=os.path.curdir): def _relpath_nt(path, start=os.path.curdir):
"""Return a relative version of a path""" """Return a relative version of a path"""
if not path: if not path:
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import base64 import base64
import sys
from mock import patch from mock import patch
from django.test import TestCase from django.test import TestCase
try:
from django.utils import unittest
except ImportError:
import unittest2 as unittest
from pipeline.conf import settings from pipeline.conf import settings
from pipeline.compressors import Compressor, TEMPLATE_FUNC from pipeline.compressors import Compressor, TEMPLATE_FUNC
...@@ -68,6 +73,9 @@ class CompressorTest(TestCase): ...@@ -68,6 +73,9 @@ class CompressorTest(TestCase):
self.assertEquals(name, 'photo_detail') self.assertEquals(name, 'photo_detail')
name = self.compressor.template_name('templates/photo_edit.jst', '') name = self.compressor.template_name('templates/photo_edit.jst', '')
self.assertEquals(name, 'photo_edit') self.assertEquals(name, 'photo_edit')
name = self.compressor.template_name('templates\photo\detail.jst',
'templates\\')
self.assertEquals(name, 'photo_detail')
def test_compile_templates(self): def test_compile_templates(self):
templates = self.compressor.compile_templates(['templates/photo/list.jst']) templates = self.compressor.compile_templates(['templates/photo/list.jst'])
...@@ -92,6 +100,12 @@ class CompressorTest(TestCase): ...@@ -92,6 +100,12 @@ class CompressorTest(TestCase):
"css/plugins/gallery.css") "css/plugins/gallery.css")
self.assertEquals(asset_path, "images/sprite.png") self.assertEquals(asset_path, "images/sprite.png")
@unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
def test_construct_asset_path_windows(self):
asset_path = self.compressor.construct_asset_path("\image\sprite.png",
"css\plugins\gallery.css")
self.assertEquals(asset_path, "http://localhost/static/images/sprite.png")
def test_construct_asset_path_relative(self): def test_construct_asset_path_relative(self):
asset_path = self.compressor.construct_asset_path("../../images/sprite.png", asset_path = self.compressor.construct_asset_path("../../images/sprite.png",
"css/plugins/gallery.css", "css/plugins/gallery.css",
...@@ -103,11 +117,10 @@ class CompressorTest(TestCase): ...@@ -103,11 +117,10 @@ class CompressorTest(TestCase):
self.assertEquals(asset_path, "/images/sprite.png") self.assertEquals(asset_path, "/images/sprite.png")
def test_url_rewrite(self): def test_url_rewrite(self):
self.maxDiff = None
output = self.compressor.concatenate_and_rewrite([ output = self.compressor.concatenate_and_rewrite([
'css/urls.css', 'css/urls.css',
]) ])
self.assertMultiLineEqual("""@font-face { self.assertEquals("""@font-face {
font-family: 'Pipeline'; font-family: 'Pipeline';
src: url(fonts/pipeline.eot); src: url(fonts/pipeline.eot);
src: url(fonts/pipeline.eot?#iefix) format('embedded-opentype'); src: url(fonts/pipeline.eot?#iefix) format('embedded-opentype');
......
...@@ -11,6 +11,7 @@ deps = ...@@ -11,6 +11,7 @@ deps =
Django==1.3.1 Django==1.3.1
mock>=0.7.2 mock>=0.7.2
django-staticfiles==1.1.2 django-staticfiles==1.1.2
unittest2==0.5.1
[testenv:docs] [testenv:docs]
basepython=python basepython=python
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment