see whatever…

jump to menu

October 8, 2009

cssutils 0.9.6final release and …

Filed under: CSS,cssutils,Python — see @ 12:53 pm

Yesterday I finally made a final release of cssutils after five alpha and four beta releases in about 10 months. This shows I sadly could not spend much time on it but actually this release has some nice stuff I think:

  • serializing is much improved (like 0.0px gets 0 now and so on)
  • some IE only values are at least parsable (alpha(…), expression(…)) and so these sheets can be minified with cssutils now
  • a complete rewrite of CSSValues (which still need a lot of work though)
  • Jython and GAE compatibility
  • added extensible CSS profiles (even someone used this for a start of a SVG profile)
  • implemented @font-face and http://www.w3.org/TR/css3-fonts/ spec (not complete probably but at least all stuff should be parsable now)
  • lots of both reported and internal bugfixes
  • lots of minor improvements…

Maybe I did this release now mainly because I wanted to start a little bit of new stuff and get this “out of the way”. Also a single (final) release in a year is the minimum I guess.

For 0.9.7 I plan some new stuff. For a long time there has been a big discussion about CSS variables and some people think they are even evil (to which I partly agree). On the other hand there seem to be quite a few CSS preprocessors (lesscss, hss, clevercss, etc) springing up so there seem to be a certain need for it. Also there is the CSS Variables spec which I think is even implemented in Webkit. So I thought why not add something like this to cssutils. People need not use it but if they want to, why not put it in this lib too ;)

So I guess I will implement the CSS Variables spec and maybe something like mix-in classes which I guess would be an extension to this and also seem to be quite useful.

A simple WSGI based CSS handler which would resolve both – variables and mix-ins – on the server would be nice. In the past I mainly used web.py but maybe I’ll try out a few other “mini-frameworks” (not sure if they like being called that but in lack of a better name) like e.g. werkzeug or bobo. If you have any preferences or suggestion please write in the comments (I prefer smaller frameworks and not bigger ones like Django for now but the results would certainly be very easily adaptable).

In addition to this (which may or may not lead to something) CSSValues still have to be reworked.

Also there is going quite a bit in the CSS world currently (the mailing list has become very lively in the last one or two years). So I guess I pick a few things which I think may be useful in the near future (and also will not take too much time to implement :) and add them to the next release.

March 8, 2009

property filter with cssutils

Filed under: cssutils — see @ 6:22 pm

cssutils 0.9.6a2 has just been released and the main new feature probably is custom property profiles. You might want to filter any given stylesheet on certain properties. This might be predefined ones (like CSS 2 properties like e.g. “color”)  or predefined ones but with a limited set of possible values or even custom properties with custom values.

Example

Following a simple example how to define a custom profile and filter any given sheet (at least style declaration properties, filtering of certain @rules is not shown):

import cssutils
# remove ALL predefined property profiles
cssutils.profile.removeProfile(all=True)

# add your custom profile, {num} is defined in Profile and always available
macros = {'myvalue': 'a|b|c'}
props = {'abc': '{myvalue}|{num}', 'color': 'red|blue'}
cssutils.profile.addProfile('my-profile', props, macros)

# keep only valid properties (valid in given profile)
cssutils.ser.prefs.validOnly = True

print cssutils.parseString('''a {
    color: green;
    color: red;
    abc: 1;
    abc: b;
    abc: 1 a
}''').cssText

results in (some messages may be doubled – not shown here – because messages are output on parsing AND during serializing):

ERROR   Property: Invalid value for "my-profile" property: green [2:9: color]
ERROR   Property: Invalid value for "my-profile" property: 1 a [6:9: abc]
a {
    color: red;
    abc: 1;
    abc: b;
    }

How to

To define your custom property profile you just need to define the properties with the possible values in a standard dictionary. Each key is a property name, each value a regular expression defining valid values. Actually the value is not (yet) a regular regular expression but may contain macros which may be used to simplify the definitions. Each macro is defined with enclosing {} and must start with [a-z]. You may define your own macros (“myvalue” in the above example) or you may use predefined macros. The basic ones are defined in cssutils.profile directly. To get a list use:

import cssutils, pprint
print "TOKEN_MACROS"
pprint.pprint(cssutils.profile._TOKEN_MACROS)
print "MACROS"
pprint.pprint(cssutils.profile._MACROS)

resulting currently in:

TOKEN_MACROS
{'escape': '{unicode}|\\\\[ -~\\200-\\777]',
 'ident': '[-]?{nmstart}{nmchar}*',
 'int': '[-]?\\d+',
 'name': '{nmchar}+',
 'nl': '\\n|\\r\\n|\\r|\\f',
 'nmchar': '[\\w-]|{nonascii}|{escape}',
 'nmstart': '[_a-z]|{nonascii}|{escape}',
 'nonascii': '[^\\0-\\177]',
 'num': '[-]?\\d+|[-]?\\d*\\.\\d+',
 'number': '{num}',
 'string': '{string1}|{string2}',
 'string1': '"(\\\\\\"|[^\\"])*"',
 'string2': "'(\\\\\\'|[^\\'])*'",
 'unicode': '\\\\[0-9a-f]{1,6}(\\r\\n|[ \\n\\r\\t\\f])?',
 'uri': 'url\\({w}({string}|(\\\\\\)|[^\\)])+){w}\\)',
 'w': '\\s*'}
MACROS
{'angle': '0|{num}(deg|grad|rad)',
 'color': '{namedcolor}|{hexcolor}|{rgbcolor}|{uicolor}',
 'frequency': '0|{num}k?Hz',
 'hexcolor': '#[0-9a-f]{3}|#[0-9a-f]{6}',
 'integer': '{int}',
 'length': '0|{num}(em|ex|px|in|cm|mm|pt|pc)',
 'namedcolor': '(transparent|orange|maroon|red|orange|yellow|olive|purple|fuchsi
a|white|lime|green|navy|blue|aqua|teal|black|silver|gray)',
 'percentage': '{num}%',
 'rgbcolor': 'rgb\\({w}{int}{w},{w}{int}{w},{w}{int}{w}\\)|rgb\\({w}{num}%{w},{w
}{num}%{w},{w}{num}%{w}\\)',
 'time': '0|{num}m?s',
 'uicolor': '(ActiveBorder|ActiveCaption|AppWorkspace|Background|ButtonFace|Butt
onHighlight|ButtonShadow|ButtonText|CaptionText|GrayText|Highlight|HighlightText
|InactiveBorder|InactiveCaption|InactiveCaptionText|InfoBackground|InfoText|Menu
|MenuText|Scrollbar|ThreeDDarkShadow|ThreeDFace|ThreeDHighlight|ThreeDLightShado
w|ThreeDShadow|Window|WindowFrame|WindowText)'}

You may also use any macro defined in the predefined profiles. As these may use other macros all have to be added (in the following example the “‘identifier” macro):

from cssutils.profiles import macros as predef
from cssutils import profile
macros = {'my-font': predef[profile.CSS_LEVEL_2]['family-name'],
          'identifier': predef[profile.CSS_LEVEL_2]['identifier']}
props = {'f': '{my-font}'}
cssutils.profile.addProfile('my-font-profile', props, macros)
print cssutils.parseString('''a {
    f: 1; /* 1 is invalid! */
    f: Arial;
}''').cssText

resulting in:

ERROR   Property: Invalid value for "my-profile2" property: 1 [2:9: f]
a {
    /* 1 is invalid! */
    f: Arial
    }

I hope this does not feel to complicate… If you have any suggestions or questions please try the cssutils Google Group.

December 26, 2008

combine and minify CSS

Filed under: CSS,cssutils — Tags: , , — see @ 12:55 pm

I have been working on minifying CSS for quite some time now and had written a simple web.py based CSS handler which does exactly that. Actually it simply uses the minify option of cssutils

Additionally the handler does combine all imported stylesheets of a given proxy sheet into a single one. Nice for development as you can split sheets into as many as you like but deploy only one. So you may have the following stylesheet style.css:

/* proxy sheet */
@import "basics.cs";
@import "layout.css";
@import "forms.css";
/* etc... */

(I normally separate styles into something similar).A given HTML page always references the single stylesheet style.css which would even work without a combinator as @imports will be loaded by the browser anyway. But for deployment or when using the simple combinator handler style.css will contain all rules from all imported sheets resulting in only a single HTTP request. If additionally minified after combination the savings on load time in most cases is substantial.

For the next release of cssutils I added a combinator function to cssutils itself:

proxysheet = cssutils.parseFile(PATH_TO_CSS) # or use parseUrl etc
combinedsheet = cssutils.resolveImports(proxysheet)
cssutils.ser.prefs.useMinified()
print combinedsheet.cssText

Based on this I thought it would be nice to have a service which does just that, resolve all imports in a given sheet, minify it and return it. So I started the CSS Minifier at GoogleAppEngine (GAE). It has a basic frontend where you enter an URL, may optionally select advanced options (for now the error level below which errors are simply swallowed, the target encoding which may currently be UTF-8 or ASCII and the option if the imports should actually be resolved).

Additionally it may be used as a simple service which returns a combined and minified sheet or in case of any errors a HTTP 400 BAD REQUEST with the error log.

The only problem on GAE was that it prevents usage of urllib/urllib2 to actually fetch the content of URLs. But it has it’s own API for that so no big problem to rewrite the fetching code. For the next cssutils release I actually added the code for GAE into cssutils itself. If cssutils thinks it runs on GAE it uses the GAE specific fetcher code, else urllib2 as before.

To detect if a script is running on GAE for now I try to “import google.appengine”. Not quite sure if that is enough but for now it seems to work.

Anyway, hope this service may be useful.

July 30, 2008

cssutils 0.9.5 final…

Filed under: CSS,cssutils — see @ 2:25 pm

After about 6 months of development 0.9.5 of cssutils is released as a final version. The last final version has been 0.6 …

Not that final means perfect but at least I tested everything, the lib itself, the scripts which have been broken in some alpha and beta releases and also the examples on the website which have been changed quite a bit. There still are quite a few areas where I suspect problems but there has to be a release at some point ;)

Anyway a release means starting a new one. I guess I have to improve the basic property handling. New values have been added to CSS2.1, CSS3 modules can be added (especially the Color Module which is almost a recommendation).

But I think I do look into other small projects first as I have been concentrating on cssutils in my spare time for quite some time now…

July 14, 2008

cssutils 0.9.5 soon

Filed under: CSS,cssutils — see @ 10:59 pm

I guess this is one of the releases I have been tested much more deeply than any others before. I know there are still lots of bugs in the lib but I did not expect such a major one which has been fixed in 0.9.5rc2. It more or less made handling lib not as it is meant to be handled. Please see the change log for a more details explanation just in short:

The global setting cssutils.log.raiseExceptions defines if exceptions when using any DOM method are actually raised (the default) or simply logged away. Problem was that whenever you used any parse* function or any CSSParser.parse* method this setting was set to “False” and exceptions were not raised anymore. Exceptions would be if the parser itself was initialized with CSSParser(raiseExceptions=True) which I reckon hardly anyone who uses the lib had done.

0.9.5rc2 fixes this bug. Any parse* does restore the original value of cssutils.log.raiseExceptions to its former defined value (which would be “True” as the default value).

I know this is normally not a time for such a serious change (at least I think it is serious, is it not?) but I think better now than later. Also there is a workaround. Simply set csstutils.log.raiseExceptions to “False” or “True” whatever you prefer. Beware though that “True” (meaning raising) should be used except during a parse* but when actually working in the DOM.

Anyway, there are also some positive things to report. A few bug have been “squashed” and the performance has been improved by maybe 25% (depending on your source sheet). This was more or less a side effect of a bugfix which made me refactor the tokenizer and realize that there is massive room for optimization…

Guess 0.9.5final will be coming shortly. The next release 0.9.6 will probably concentrate on properties and values which are not testet very well and do have room for optimization – speaking positively ;)

June 16, 2008

build a web.py egg (0.23)

Filed under: Python,Web — see @ 8:49 pm

To “get an egg” from web.py just download and untar the archive from the website and edit setup.py:

#from distutils.core import setup

try:
from setuptools import setup, find_packages
except ImportError:
from ez_setup import use_setuptools
use_setuptools()
from setuptools import setup, find_packages

You obviously need setuptools installed or at least ez_setup (if you don’t know that you won’t need an egg either ;) )

Then just do:

>setup.py bdist_egg

and the egg will be found in folder dist…

Wonder why they only use distutils which cannot build eggs by itself. Anyway it is simple.

I just needed the egg as I try to minimize the need of installed libs and just pack it with an web.py application.

May 17, 2008

Compiling Python modules extensions on Windows

Filed under: Python — see @ 8:56 pm

Obviously I have no real knowledge of C and am working mostly on Windows which does not have a C compiler installed normally. But I sometimes need a Python module which use C extensions (like lxml or simplejson). Problem is if no egg is available until now I had no way to install the module :(

I always wanted to get this to work and it is not that difficult…

A reminder for me (and maybe other folks who are interested) here the steps I used found (great overview) on various (additional hack) websites combined in a simple step by step overview. (Used on Windows Vista with Python 2.5.2 and the versions stated below.)

  1. Download MinGW, the Automated Installer is sufficient. I just selected “g++” and “make”, am not sure if that is needed afterall. Version I used is 5.1.4. Install it to “c:\mingw” (recommended for Vista and I only tried under Vista yet)
  2. Set MingW32 as the compiler for distutils by adding %PYTHONHOME%\lib\distutils\distutils.cfg with the following content:
    [build]
    compiler = mingw32
  3. The current version of MingW seems to trigger a small problem with distutils so you need to hack %PYTHONHOME%\lib\distutils\version.py and replace the definition of version_re (no actual functionality but just a new versioning system which seems to confuse distutils) with this:
    version_re = re.compile(r'^(\d+) \. (\d+) (\. (\d+))? (\. (\d+))? ([ab](\d+))?$',re.VERBOSE)
  4. save the following commands in a batch file which do set all needed environment vars etc:
    @echo off
    
    echo MinGW Enviroment Command Console
    echo ....
    echo ....
    @set MINGWROOT=C:\MinGW
    @set MINGWBIN=%MINGWROOT%\bin
    @set MINGWINCLUDE=%MINGWROOT%\include
    @set MINGWLIB=%MINGWROOT%\lib
    @set MINGWLIBEXEC=%MINGWROOT%\libexec\gcc\mingw32\3.4.5
    @set MINGWBIN2=%MINGWROOT%\mingw32\bin
    @set MINGWLIB2=%MINGWROOT%\mingw32\lib\ldscripts
    @set MINGW=%MINGWROOT%;%MINGWBIN%;%MINGWINCLUDE%;%MINGWLIB%;%MINGWLIBEXEC%;%MINGWLIB2%;%MINGWLIB2%
    
    rem to add more resource paths just use the set command like above and the and it to the set PATH like below
    
    @set Path=%MINGW%;%Path%

All is set so you can start to try it out. Start a command prompt and run the batch file created in step 4. Now use easy_install to install the lib you need (you may also use a simple setup.py install but I find easy_install so much easier and most projects use it nowadays):

easy_install "simplejson==1.9.1"

which should download simplejson version 1.9.1, compile the C extensions and save an egg to %PYTHONHOME%\Lib\site-packages\simplejson-1.9.1-py2.5-win32.egg.

Not that difficult after all (if you have the help of the pages linked to above ;) ). Guess I should have tried it earlier as I actually have used jsonlib in favor of simplejson for the simple fact that jsonlib was easier to install but simplejson seems to be in favor for going into the stdlib.

May 13, 2008

cssutils ongoings

Filed under: CSS,cssutils — see @ 10:12 pm

I am busy with a few other things so the new release of cssutils is coming up a bit slow.

A few changes (and not even very minor) have been added to trunk and so next beta will have them. I know they should have been in an alpha release but it’s all just tags…

I guess after this beta (maybe I find the time in the next 2 weeks or so) there will even be a “final” release for the current version 0.9.5. There has not been a “final” release of any version since – I really don’t know – maybe 0.5.3? But maybe doing some alphas, betas and a final is better than just leave it with a beta?

Anyway, there is work underway and hopefully a new release this month. (I guess this post is mostly to keep myself actually doing it…)

April 21, 2008

CSS validator on Google AppEngine

Filed under: CSS,cssutils,Python — Tags: , — see @ 10:37 pm

After I got my AppEngine invitation last weekend I put a very simple CSS validator application together (based on the guestbook demo ;) ). No info or style yet and not complete either but I wanted to play around with AppEngine.

One problem is that apps cannot make URL requests via urllib so actually resolving @import rules in given CSS sheets does not work currently. I guess I need to rewrite the underlying cssutils library a bit to actually use Googles urlfetch lib. Seems easy, only missing thing is time ;)

March 24, 2008

cssutils 0.9.5b2

Filed under: CSS,cssutils — see @ 12:40 am

Already a new release. At least the broken features in b1 are fixed. There are a few open ends but nothing that serious.

Also the fixes did not take as much time as expected. And a few other minor fixes are onboard as well. I guess cssutils is getting better and better (still hardly good enough though ;) )

There probably will be one or two further 0.9.5 beta releases before I start on 0.9.6. There are a few things I like to really check out before delving into stuff like querying a stylesheet (hope at least to get started with it for 0.9.6) and maybe registration of property validation and maybe also custom @rules. There are also a few other areas I would like to do (if I get the time) namely optimizing serialization which would be nice if ordered by selector specificity (indented more as specificity gets higher, I do this when writing CSS by hand but hope to make this happen automatic). And I guess reworking the whole CSSValue stuff which is redefined in CSSOM as compared to CSS 2.1 DOM would be good to do sooner than later.

let’s see…

Older Posts »

Powered by WordPress