# HG changeset patch # User Florent Cayré # Date 1304015067 -7200 # Node ID f9a68136eb878ccbb094efd3732fa54df3ebeb96 # Parent bb3bb8104134165d8162cee03a0675a7cdebbd77 handle js/ css file concatenation with twisted diff -r bb3bb8104134 -r f9a68136eb87 etwist/server.py --- a/etwist/server.py Thu Apr 28 19:42:19 2011 +0200 +++ b/etwist/server.py Thu Apr 28 20:24:27 2011 +0200 @@ -17,6 +17,8 @@ # with CubicWeb. If not, see . """twisted server for CubicWeb web instances""" +from __future__ import with_statement + __docformat__ = "restructuredtext en" import sys @@ -26,6 +28,8 @@ import errno import traceback import threading +import re +import hashlib from os.path import join from time import mktime from datetime import date, timedelta @@ -42,7 +46,8 @@ from logilab.common.decorators import monkeypatch -from cubicweb import AuthenticationError, ConfigurationError, CW_EVENT_MANAGER +from cubicweb import (AuthenticationError, ConfigurationError, + CW_EVENT_MANAGER, CubicWebException) from cubicweb.utils import json_dumps from cubicweb.web import Redirect, DirectResponse, StatusResponse, LogOut from cubicweb.web.application import CubicWebPublisher @@ -79,6 +84,7 @@ class DataLookupDirectory(NoListingFile): def __init__(self, config, path): + self.md5_version = config.instance_md5_version() NoListingFile.__init__(self, path) self.config = config self.here = path @@ -87,12 +93,24 @@ # that ? self.putChild('fckeditor', FCKEditorResource(self.config, '')) self._defineChildResources() + if self.config.debugmode: + self.data_modconcat_basepath = '/data/??' + else: + self.data_modconcat_basepath = '/data/%s/??' % self.md5_version def _defineChildResources(self): - self.putChild(self.config.instance_md5_version(), self) + self.putChild(self.md5_version, self) def getChild(self, path, request): if not path: + if request.uri.startswith(self.data_modconcat_basepath): + resource_relpath = request.uri[len(self.data_modconcat_basepath):] + if resource_relpath: + paths = resource_relpath.split(',') + try: + return ConcatFiles(self.config, paths) + except ConcatFileNotFoundError: + return self.childNotFound return self.directoryListing() childpath = join(self.here, path) dirpath, rid = self.config.locate_resource(childpath) @@ -149,6 +167,34 @@ return DataLookupDirectory.render(self, request) +class ConcatFileNotFoundError(CubicWebException): + pass + + +class ConcatFiles(LongTimeExpiringFile): + def __init__(self, config, paths): + path = self._concat_cached_filepath(config, paths) + LongTimeExpiringFile.__init__(self, config, path) + + @staticmethod + def _concat_cached_filepath(config, paths): + _, ext = osp.splitext(paths[0]) + # create a unique / predictable filename + fname = hashlib.md5(';'.join(paths)).hexdigest() + ext + filepath = osp.join(config.appdatahome, 'uicache', fname) + if not osp.isfile(filepath): + concat_data = [] + for path in paths: + dirpath, rid = config.locate_resource(path) + if rid is None: + raise ConcatFileNotFoundError(path) + concat_data.append(open(osp.join(dirpath, rid)).read()) + with open(filepath, 'wb') as f: + f.write('\n'.join(concat_data)) + return filepath + + + class CubicWebRootResource(resource.Resource): def __init__(self, config, vreg=None): resource.Resource.__init__(self)