Commits

Alessandro Molina committed 9c83541

First import

  • Participants

Comments (0)

Files changed (7)

+syntax: glob
+
+.idea
+*.pyc
+*.egg-info
+About tgext.scss
+-------------------------
+
+`SCSS <http://sass-lang.com/>`_ is a cool and useful extension to CSS,
+but it always required some effort to be used and even
+specific production environment configurations for some systems.
+
+tgext.scss has born to make life easier for `TurboGears2  <http://www.turbogears.org>`_ developers,
+it will rely on `python-scss <http://packages.python.org/scss/>`_ to serve all the files in your public directory
+that end with *.scss* as **text/css** converting them and minifying them.
+
+Installing
+-------------------------------
+
+tgext.scss can be installed both from pypi or from bitbucket::
+
+    easy_install tgext.scss
+
+should just work for most of the users
+
+Enabling tgext.scss
+----------------------------------
+
+Using tgext.scss is really simple, you edit your `config/middeware.py` and just after 
+the `#Wrap your base TurboGears 2 application with custom middleware here` comment wrap
+`app` with `SCSSMiddleware`::
+
+    from tgext.scss import SCSSMiddleware
+
+    make_base_app = base_config.setup_tg_wsgi_app(load_environment)
+
+    def make_app(global_conf, full_stack=True, **app_conf):
+        app = make_base_app(global_conf, full_stack=True, **app_conf)
+
+        # Wrap your base TurboGears 2 application with custom middleware here
+        app = SCSSMiddleware(app)
+    
+        return app
+
+
+Now you just have to put your .scss file inside *public/css* and they will be served as CSS.
+
+How much it will slow me down?
+-----------------------------------
+
+Actually as tgext.scss uses aggressive caching it won't you slow down at all,
+indeed it might even be able to serve you CSS files even faster.
+
+Here is the report of a benchmark (absolutely not reliable as every other benchmark)
+made on paster serving the same CSS file or SCSS::
+
+    $ /usr/sbin/ab -n 1000 http://localhost:8080/css/style.css
+    Requests per second:    961.26 [#/sec] (mean)
+
+    $ /usr/sbin/ab -n 1000 http://localhost:8080/css/style.scss
+    Requests per second:    1200.34 [#/sec] (mean)
+
+In these case SCSS is even faster than directly serving the same css file as
+it is served from memory (due to caching perfmed by tgext.scss)
+and is also minified resulting in less bandwith usage.
+
+Off course this means that tgext.scss will require a bit more memory than serving
+your css files alone, but as css files are usually small this amount is trascurable.
+[egg_info]
+tag_build = dev
+tag_svn_revision = true
+from setuptools import setup, find_packages
+import sys, os
+
+version = '0.1'
+
+here = os.path.abspath(os.path.dirname(__file__))
+try:
+    README = open(os.path.join(here, 'README.rst')).read()
+except IOError:
+    README = ''
+
+setup(name='tgext.scss',
+      version=version,
+      description="SCSS for TurboGears2, fast middleware to use SCSS for all your CSS",
+      long_description=README,
+      classifiers=[
+        "Environment :: Web Environment",
+        "Topic :: Software Development :: Libraries :: Python Modules",
+        "Framework :: TurboGears"
+        ],
+      keywords='turbogears2.extension SCSS WSGI',
+      author='Alessandro Molina',
+      author_email='alessandro.molina@axant.it',
+      url='http://bitbucket.org/_amol_/tgext.scss',
+      license='MIT',
+      packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
+      namespace_packages=['tgext'],
+      include_package_data=True,
+      package_data = {'':['*.html', '*.js', '*.css', '*.png', '*.gif']},
+      zip_safe=False,
+      install_requires=[
+        "TurboGears2 >= 2.0b7",
+        "scss"
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )

File tgext/__init__.py

+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

File tgext/scss/__init__.py

+from middleware import SCSSMiddleware

File tgext/scss/middleware.py

+import os, os.path
+from webob import Request, Response
+from webob.exc import status_map
+from scss import parser
+from tg import config
+
+class SCSSMiddleware(object):
+    def __init__(self, app):
+        self.app = app
+        self.cache = {}
+        self.root_directory = os.path.normcase(os.path.abspath((config['pylons.paths']['static_files'])))
+
+    def convert(self, text):
+        p = parser.Stylesheet(options=dict(compress=True, comments=False))
+        return p.loads(text)
+
+    def __call__(self, environ, start_response):
+        requested_path = environ['PATH_INFO']
+        if requested_path[-5:] != '.scss':
+            return self.app(environ, start_response)
+
+        full = os.path.normcase(os.path.abspath((os.path.join(self.root_directory, requested_path[1:]))))
+        if not os.path.exists(full):
+            return status_map[404]()(environ, start_response)
+
+        etag_key = '"%s"' % os.stat(full).st_mtime
+        if_none_match = environ.get('HTTP_IF_NONE_MATCH')
+        if if_none_match and etag_key == if_none_match:
+            start_response('304 Not Modified', (('ETag', etag_key),))
+            return ['']
+
+        cached_data = self.cache.get(requested_path)
+        if not cached_data or cached_data['etag_key'] != etag_key:
+            content = open(full)
+            cached_data = {'content':self.convert(content.read()),
+                           'etag_key':etag_key}
+            self.cache[requested_path] = cached_data
+            content.close()
+
+        response = Response()
+        response.content_type = 'text/css'
+        response.headers['ETag'] = etag_key
+        response.body = cached_data['content']
+        return response(environ, start_response)