<s> from __future__ import with_statement <EOL> import math <EOL> import os <EOL> import shutil <EOL> import subprocess <EOL> import re <EOL> from StringIO import StringIO <EOL> from media_bundler . conf import bundler_settings <EOL> from media_bundler . bin_packing import Box , pack_boxes <EOL> from media_bundler . jsmin import jsmin <EOL> from media_bundler . cssmin import minify_css <EOL> from media_bundler import versioning <EOL> class InvalidBundleType ( Exception ) : <EOL> def __init__ ( self , type_ ) : <EOL> msg = "<STR_LIT>" % type_ <EOL> super ( InvalidBundleType , self ) . __init__ ( msg ) <EOL> def concatenate_files ( paths ) : <EOL> """<STR_LIT>""" <EOL> for path in paths : <EOL> with open ( path ) as input : <EOL> buffer = input . read ( <NUM_LIT> ) <EOL> while buffer : <EOL> yield buffer <EOL> buffer = input . read ( <NUM_LIT> ) <EOL> class Bundle ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , name , path , url , files , type ) : <EOL> self . name = name <EOL> self . path = path <EOL> self . url = url <EOL> if not url . endswith ( "<STR_LIT:/>" ) : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> self . files = files <EOL> self . type = type <EOL> @ classmethod <EOL> def check_attr ( cls , attrs , attr ) : <EOL> errmsg = "<STR_LIT>" % ( attrs , attr ) <EOL> assert attr in attrs , errmsg <EOL> @ classmethod <EOL> def from_dict ( cls , attrs ) : <EOL> for attr in ( "<STR_LIT:type>" , "<STR_LIT:name>" , "<STR_LIT:path>" , "<STR_LIT:url>" , "<STR_LIT>" ) : <EOL> cls . check_attr ( attrs , attr ) <EOL> if attrs [ "<STR_LIT:type>" ] == "<STR_LIT>" : <EOL> return JavascriptBundle ( attrs [ "<STR_LIT:name>" ] , attrs [ "<STR_LIT:path>" ] , attrs [ "<STR_LIT:url>" ] , <EOL> attrs [ "<STR_LIT>" ] , attrs [ "<STR_LIT:type>" ] , <EOL> attrs . get ( "<STR_LIT>" , False ) ) <EOL> elif attrs [ "<STR_LIT:type>" ] == "<STR_LIT>" : <EOL> return CssBundle ( attrs [ "<STR_LIT:name>" ] , attrs [ "<STR_LIT:path>" ] , attrs [ "<STR_LIT:url>" ] , <EOL> attrs [ "<STR_LIT>" ] , attrs [ "<STR_LIT:type>" ] , <EOL> attrs . get ( "<STR_LIT>" , False ) ) <EOL> elif attrs [ "<STR_LIT:type>" ] == "<STR_LIT>" : <EOL> cls . check_attr ( attrs , "<STR_LIT>" ) <EOL> return PngSpriteBundle ( attrs [ "<STR_LIT:name>" ] , attrs [ "<STR_LIT:path>" ] , attrs [ "<STR_LIT:url>" ] , <EOL> attrs [ "<STR_LIT>" ] , attrs [ "<STR_LIT:type>" ] , <EOL> attrs [ "<STR_LIT>" ] ) <EOL> else : <EOL> raise InvalidBundleType ( attrs [ "<STR_LIT:type>" ] ) <EOL> def get_paths ( self ) : <EOL> return [ os . path . join ( self . path , f ) for f in self . files ] <EOL> def get_extension ( self ) : <EOL> raise NotImplementedError <EOL> def get_bundle_filename ( self ) : <EOL> return self . name + self . get_extension ( ) <EOL> def get_bundle_path ( self ) : <EOL> filename = self . get_bundle_filename ( ) <EOL> return os . path . join ( self . path , filename ) <EOL> def get_bundle_url ( self ) : <EOL> unversioned = self . get_bundle_filename ( ) <EOL> filename = versioning . get_bundle_versions ( ) . get ( self . name , unversioned ) <EOL> return self . url + filename <EOL> def make_bundle ( self , versioner ) : <EOL> self . _make_bundle ( ) <EOL> if versioner : <EOL> versioner . update_bundle_version ( self ) <EOL> def do_text_bundle ( self , minifier = None ) : <EOL> with open ( self . get_bundle_path ( ) , "<STR_LIT:w>" ) as output : <EOL> generator = concatenate_files ( self . get_paths ( ) ) <EOL> if minifier : <EOL> output . write ( minifier ( "<STR_LIT>" . join ( generator ) ) ) <EOL> else : <EOL> output . write ( "<STR_LIT>" . join ( generator ) ) <EOL> class JavascriptBundle ( Bundle ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , name , path , url , files , type , minify ) : <EOL> super ( JavascriptBundle , self ) . __init__ ( name , path , url , files , type ) <EOL> self . minify = minify <EOL> def get_extension ( self ) : <EOL> return "<STR_LIT>" <EOL> def _make_bundle ( self ) : <EOL> minifier = jsmin if self . minify else None <EOL> self . do_text_bundle ( minifier ) <EOL> class CssBundle ( Bundle ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , name , path , url , files , type , minify ) : <EOL> super ( CssBundle , self ) . __init__ ( name , path , url , files , type ) <EOL> self . minify = minify <EOL> def get_extension ( self ) : <EOL> return "<STR_LIT>" <EOL> def _make_bundle ( self ) : <EOL> minifier = minify_css if self . minify else None <EOL> self . do_text_bundle ( minifier ) <EOL> class PngSpriteBundle ( Bundle ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , name , path , url , files , type , css_file ) : <EOL> super ( PngSpriteBundle , self ) . __init__ ( name , path , url , files , type ) <EOL> self . css_file = css_file <EOL> def get_extension ( self ) : <EOL> return "<STR_LIT>" <EOL> def make_bundle ( self , versioner ) : <EOL> import Image <EOL> boxes = [ ImageBox ( Image . open ( path ) , path ) for path in self . get_paths ( ) ] <EOL> total_area = sum ( box . width * box . height for box in boxes ) <EOL> width = max ( max ( box . width for box in boxes ) , <EOL> ( int ( math . sqrt ( total_area ) ) // <NUM_LIT:16> + <NUM_LIT:1> ) * <NUM_LIT:16> ) <EOL> ( _ , height , packing ) = pack_boxes ( boxes , width ) <EOL> sprite = Image . new ( "<STR_LIT>" , ( width , height ) ) <EOL> for ( left , top , box ) in packing : <EOL> img = box . image <EOL> mask = img if img . mode == "<STR_LIT>" else None <EOL> sprite . paste ( img , ( left , top ) , mask ) <EOL> sprite . save ( self . get_bundle_path ( ) , "<STR_LIT>" ) <EOL> self . _optimize_output ( ) <EOL> if versioner : <EOL> versioner . update_bundle_version ( self ) <EOL> self . generate_css ( packing ) <EOL> def _optimize_output ( self ) : <EOL> """<STR_LIT>""" <EOL> sprite_path = self . get_bundle_path ( ) <EOL> tmp_path = sprite_path + '<STR_LIT>' <EOL> args = [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , sprite_path , tmp_path ] <EOL> proc = subprocess . Popen ( args , stdout = subprocess . PIPE , <EOL> stderr = subprocess . STDOUT ) <EOL> proc . wait ( ) <EOL> if proc . returncode != <NUM_LIT:0> : <EOL> raise Exception ( '<STR_LIT>' <EOL> '<STR_LIT:%s>' % ( proc . returncode , proc . stdout . read ( ) ) ) <EOL> shutil . move ( tmp_path , sprite_path ) <EOL> def generate_css ( self , packing ) : <EOL> """<STR_LIT>""" <EOL> with open ( self . css_file , "<STR_LIT:w>" ) as css : <EOL> css . write ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> props = { <EOL> "<STR_LIT>" : "<STR_LIT>" % self . get_bundle_url ( ) , <EOL> } <EOL> css . write ( self . make_css ( None , props ) ) <EOL> for ( left , top , box ) in packing : <EOL> props = { <EOL> "<STR_LIT>" : "<STR_LIT>" % ( - left , - top ) , <EOL> "<STR_LIT:width>" : "<STR_LIT>" % box . width , <EOL> "<STR_LIT>" : "<STR_LIT>" % box . height , <EOL> } <EOL> css . write ( self . make_css ( os . path . basename ( box . filename ) , props ) ) <EOL> CSS_REGEXP = re . compile ( r"<STR_LIT>" ) <EOL> def css_class_name ( self , rule_name ) : <EOL> name = self . name <EOL> if rule_name : <EOL> name += "<STR_LIT:->" + rule_name <EOL> name = name . replace ( "<STR_LIT:U+0020>" , "<STR_LIT:->" ) . replace ( "<STR_LIT:.>" , "<STR_LIT:->" ) <EOL> return self . CSS_REGEXP . sub ( "<STR_LIT>" , name ) <EOL> def make_css ( self , name , props ) : <EOL> css_class = self . css_class_name ( name ) <EOL> css_propstr = "<STR_LIT>" . join ( "<STR_LIT>" % p for p in props . iteritems ( ) ) <EOL> return "<STR_LIT>" % ( css_class , css_propstr ) <EOL> class ImageBox ( Box ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , image , filename ) : <EOL> ( width , height ) = image . size <EOL> super ( ImageBox , self ) . __init__ ( width , height ) <EOL> self . image = image <EOL> self . filename = filename <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" % ( self . filename , self . image ) <EOL> _bundles = None <EOL> def get_bundles ( ) : <EOL> """<STR_LIT>""" <EOL> global _bundles <EOL> if not _bundles : <EOL> _bundles = dict ( ( bundle [ "<STR_LIT:name>" ] , Bundle . from_dict ( bundle ) ) <EOL> for bundle in bundler_settings . MEDIA_BUNDLES ) <EOL> return _bundles </s>
