@import ... wrt what?

36 views
Skip to first unread message

Dave Pawson

unread,
Jun 9, 2009, 4:37:03 AM6/9/09
to CSSUtils
A CSS file, in use, takes imported files relative to the current CSS
file location (I think)
http://www.w3.org/TR/CSS2/cascade.html#at-import - where It is not mentioned.
Nor in http://www.w3.org/TR/2009/CR-CSS2-20090423/

cssutils complains when the import is not relative to the Python
script being run?

Is that correct?
Is it a bug?

Is it not specified?


regards

--
Dave Pawson
XSLT XSL-FO FAQ.
Docbook FAQ.
http://www.dpawson.co.uk

see

unread,
Jun 9, 2009, 1:44:30 PM6/9/09
to cssutils
I currently don't know where but it is specified that imports are
relative to the importing files. Nevertheless you might have to tell
cssutils where the importing sheet sits. it all depends how hrefs are
given in the @import rules. If they are relative it should work easy
but for path absolute paths (e.g. "/imported.css") this is a different
thing. Please see

http://cssutils.googlecode.com/svn/trunk/docs/html/docs/parse.html#cssparser

the parameter "href" is for this. You might also be interested in the
custom fetcher described on the same page.

Dave Pawson

unread,
Jun 9, 2009, 2:22:11 PM6/9/09
to cssutils
2009/6/9 see <cth...@gmail.com>:

>
> I currently don't know where but it is specified that imports are
> relative to the importing files.

So I have a CSS file:
contains @import url('t.generic.css');

I'd expect that to import from the same directory as the containing file?


Nevertheless you might have to tell
> cssutils where the importing sheet sits. it all depends how hrefs are
> given in the @import rules. If they are relative it should work easy
> but for path absolute paths (e.g. "/imported.css") this is a different
> thing. Please see
>
> http://cssutils.googlecode.com/svn/trunk/docs/html/docs/parse.html#cssparser
>
> the parameter "href" is for this.

<quote>If href is given it is set as sheet.href. Either way sheet.href
is used to resolve e.g. stylesheet imports via @import rules. </

Sorry Chris, I don't understand how that relates to my case?


You might also be interested in the
> custom fetcher described on the same page.

<quote>The fetcher is called when an @import rule is found and the
referenced stylesheet is about to be retrieved.</

OK, that I understand.

I may have to use that, although I think my usecase matches your description,
so why it is looking for a CSS file relative to the location of the
python Script I don't know.

see

unread,
Jun 9, 2009, 3:10:20 PM6/9/09
to cssutils
> So I have a CSS file:
> contains @import url('t.generic.css');
>
> I'd expect that to import from the same directory as the containing file?

yes (parameter href of the parse methods is None in this case). I just
checked and it works (at least on Windows that is). You might want to
check attribute "href" of:

- importrule.href is the href given in the @import rule like
"t.generic.css" above
- importrule.styleSheet.href is the absolute path of the imported
sheet. May look a bit strange but an @import rule has the href given
in the sheet but the parsed stylesheet has the absolute path. This
path is not reserialized but only used to resolve any imports so it is
set by cssutils that way.

>
>  Nevertheless you might have to tell
>
> > cssutils where the importing sheet sits. it all depends how hrefs are
> > given in the @import rules. If they are relative it should work easy
> > but for path absolute paths (e.g. "/imported.css") this is a different
> > thing. Please see
>
> >http://cssutils.googlecode.com/svn/trunk/docs/html/docs/parse.html#cs...
>
> > the parameter "href" is for this.
>
> <quote>If href is given it is set as sheet.href. Either way sheet.href
> is used to resolve e.g. stylesheet imports via @import rules. </
>
> Sorry Chris, I don't understand how that relates to my case?

If you do not give any href as parameter to parse in your case this
should just work. If you would e.g. parse a sheet on the web you might
have to overwrite the "base" href of the importing sheet.


> You might also be intested in the
> custom fetcher described on the same page.
>
> <quote>The fetcher is called when an @import rule is found and the
> referenced stylesheet is about to be retrieved.</
>
> OK, that I understand.
>
> I may have to use that, although I think my usecase matches your description,
> so why it is looking for a CSS file relative to the location of the
> python Script I don't know.

check the hrefs as above and also what OS are you working on? And are
you using parseFile when working locally or maybe parseString? You
should be using parseFile I guess

Dave Pawson

unread,
Jun 10, 2009, 9:04:46 AM6/10/09
to see, cssutils
2009/6/9 see <cth...@gmail.com>:

>
>> So I have a CSS file:
>> contains @import url('t.generic.css');
>>
>> I'd expect that to import from the same directory as the containing file?
>
> yes (parameter href of the parse methods is None in this case). I just
> checked and it works (at least on Windows that is). You might want to
> check attribute "href" of:
>
> - importrule.href is the href given in the @import rule like
> "t.generic.css" above
> - importrule.styleSheet.href is the absolute path of the imported
> sheet. May look a bit strange but an @import rule has the href given
> in the sheet but the parsed stylesheet has the absolute path. This
> path is not reserialized but only used to resolve any imports so it is
> set by cssutils that way.


Error
WARNING [Errno 2] No such file or directory:
'/d/shared/cakes/php/etc/t.generic.css'
WARNING CSSImportRule: While processing imported style sheet
href=u't.generic.css': IOError('Cannot read Stylesheet.',)

Running on Linux.

Tried

if rule.type == rule.IMPORT_RULE:
imp=cssutils.css.CSSImportRule(href="/d/shared/cakes/php/css")
print "import ", imp.href

Since I'm processing a number of stylesheets, I don't know the url of
the imported stylesheet.

>
>>
>>  Nevertheless you might have to tell
>>
>> > cssutils where the importing sheet sits. it all depends how hrefs are
>> > given in the @import rules. If they are relative it should work easy
>> > but for path absolute paths (e.g. "/imported.css") this is a different
>> > thing. Please see
>>
>> >http://cssutils.googlecode.com/svn/trunk/docs/html/docs/parse.html#cs...
>>
>> > the parameter "href" is for this.
>>
>> <quote>If href is given it is set as sheet.href. Either way sheet.href
>> is used to resolve e.g. stylesheet imports via @import rules. </
>>
>> Sorry Chris, I don't understand how that relates to my case?
>
> If you do not give any href as parameter to parse in your case this
> should just work. If you would e.g. parse a sheet on the web you might
> have to overwrite the "base" href of the importing sheet.


OK, I added
parser=cssutils.CSSParser()
sheet = parser.parseFile(item,'utf-8', href="/d/shared/cakes/php/css"")

Still shows the same error

> check the hrefs as above and also what OS are you working on? And are
> you using parseFile when working locally or maybe parseString? You
> should be using parseFile I guess

Yes, as above, parsefile.

On Linux, fedora 10.

see

unread,
Jun 10, 2009, 9:59:13 AM6/10/09
to cssutils
> Error
> WARNING [Errno 2] No such file or directory:
> '/d/shared/cakes/php/etc/t.generic.css'
> WARNING CSSImportRule: While processing imported style sheet
> href=u't.generic.css': IOError('Cannot read Stylesheet.',)
>
> Running on Linux.
>
> Tried
>
>         if rule.type == rule.IMPORT_RULE:
>             imp=cssutils.css.CSSImportRule(href="/d/shared/cakes/php/css")
>             print "import ", imp.href
>
> Since I'm processing a number of stylesheets, I don't know the url of
> the imported stylesheet.

Any way to use a file URL for href? Something like file:...? I guess
this may be a problem with urllib2 which is used to read the imported
sheets and a file ref on OS level might not work. You might also want
to try a relative path something like "shared/cakes/php/css/file.css".
I also think you need the full file path and not just the folder.

I do not have access to a Unix system currently so cannot check
really...

Dave Pawson

unread,
Jun 10, 2009, 10:43:02 AM6/10/09
to see, cssutils
2009/6/10 see <cth...@gmail.com>:

>> Running on Linux.
>>
>> Tried
>>
>>         if rule.type == rule.IMPORT_RULE:
>>             imp=cssutils.css.CSSImportRule(href="/d/shared/cakes/php/css")
>>             print "import ", imp.href
>>
>> Since I'm processing a number of stylesheets, I don't know the url of
>> the imported stylesheet.
>
> Any way to use a file URL for href? Something like file:...? I guess
> this may be a problem with urllib2 which is used to read the imported
> sheets and a file ref on OS level might not work.

file::// is a valid url.

You might also want
> to try a relative path something like "shared/cakes/php/css/file.css".
> I also think you need the full file path and not just the folder.

The imported file is in the same directory as the importing file,
thats what is puzzling. A relative file should work.
It's the 'base' that seems to be set to the current working directory.


>
> I do not have access to a Unix system currently so cannot check
> really...

Can you think of an easy test that we could run on windows and Linux
to add to your test harnesses?

Dave Pawson

unread,
Jun 10, 2009, 10:53:05 AM6/10/09
to see, cssutils
Little more information

WARNING [Errno 2] No such file or directory:
'/d/shared/cakes/php/etc/t.generic.css'
WARNING CSSImportRule: While processing imported style sheet
href=u't.generic.css': IOError('Cannot read Stylesheet.',)
WARNING [Errno 2] No such file or directory:
'/d/shared/cakes/php/etc/t.generic.css'
WARNING CSSImportRule: While processing imported style sheet
href=u't.generic.css': IOError('Cannot read Stylesheet.',)

import file:///d/shared/cakes/php/css/t.generic.css


This after adding

if rule.type == rule.IMPORT_RULE:
imp=cssutils.css.CSSImportRule(href="file:///d/shared/cakes/php/css/t.generic.css")

So a full url using file:// doesn't work either?

Note that the import (in the CSS stylesheet) is still showing relative
to .../etc
where the Python is.
I.e the cssutils.css.CSSImportRule isn't affecting the actual import statement?

see

unread,
Jun 10, 2009, 11:33:21 AM6/10/09
to cssutils
could you give a complete but simplified example?

The following does work with me:

. = current working directory
./sheets/ = where other sheets are (actually the ones in the cssutils
SVN trunk)
./sheets/import.css = does itself import another sheet
./sheets/import/import2.css = is imported by ./sheets/import.css

then the following does work:

>>> import cssutils
>>> s = cssutils.parseString('@import "sheets/import.css";')
>>> s.cssText
'@import "sheets/import.css";'
>>> s.cssRules[0].styleSheet.cssText
'@import "import/import2.css";\na {\n background-image: url(test/
x.gif)\n
}\n/* import.css*/'
>>>

and also:

>>> s = cssutils.parseFile('sheets/import.css')
>>> s.cssText
'@import "import/import2.css";\na {\n background-image: url(test/
x.gif)\n
}\n/* import.css*/'
>>> s.cssRules[0].styleSheet.cssText
'@import "../import3.css";\n/* sheets/import2.css */'

On Windows even somethink like

>>> s = cssutils.parseFile('C:\\workspace\\cssutils-trunk\\sheets\\import.
css')

does work. Maybe this is a problem on Unix (with your absolute path as
above)?
Could you try this setup? All files are on Google Code SVN but they
are very very basic so you could just write them yourself.

Dave Pawson

unread,
Jun 10, 2009, 1:41:12 PM6/10/09
to cssutils
2009/6/10 see <cth...@gmail.com>:


OK. Possible differences, but same setup.

run from . with all stylesheets in ./sheets
python script in .

parser=cssutils.CSSParser() #return a DOM Level 2 CSS StyleSheet object


sheet = parser.parseFile(item,'utf-8',

href="sheets/import.css")

def checkrules(sheet):
nrules = sheet.cssRules.length

for item in range(0 , nrules):
rule = sheet.cssRules[item] #class cssutils.css.CSSRule

if rule.type == rule.IMPORT_RULE:
imp=cssutils.css.CSSImportRule(href="file:///files/css/cssutilsTest/sheets/import.css")
print "import ", imp.href

Shows :

[dpawson@marge cssutilsTest]$ python csscheck.py
WARNING ValueError, unknown url type: sheets/imported.css


WARNING CSSImportRule: While processing imported style sheet

href=u'imported.css': IOError('Cannot read Stylesheet.',)
WARNING ValueError, unknown url type: sheets/imported.css


WARNING CSSImportRule: While processing imported style sheet

href=u'imported.css': IOError('Cannot read Stylesheet.',)
******************* Checking sheets/import.css **********************


WARNING [Errno 2] No such file or directory:

'/files/css/cssutilsTest/imported.css'


WARNING CSSImportRule: While processing imported style sheet

href=u'imported.css': IOError('Cannot read Stylesheet.',)


WARNING [Errno 2] No such file or directory:

'/files/css/cssutilsTest/imported.css'


WARNING CSSImportRule: While processing imported style sheet

href=u'imported.css': IOError('Cannot read Stylesheet.',)
import file:///files/css/cssutilsTest/sheets/import.css


Warnings, but still seems wrong somehow.

see

unread,
Jun 10, 2009, 2:33:02 PM6/10/09
to cssutils
> OK. Possible differences, but same setup.
>
> run from . with all stylesheets in ./sheets
> python script in .
>
>   parser=cssutils.CSSParser() #return a DOM Level 2 CSS StyleSheet object
>         sheet = parser.parseFile(item,'utf-8',
>                                  href="sheets/import.css")

what is item here? the filename I guess?

first parameter to parseFile is the filename and it is NOT href. href
is only needed when parsing any URL on the net. just omit the href
parameter. Please check my example above.
Also href must be a valid URL and "sheets/import.css" is not (at least
not a full URL). But just omit it and you should be fine.

see

unread,
Jun 11, 2009, 6:49:35 AM6/11/09
to cssutils
I changed a few lines in your example, see below the comments starting
with CHANGE:


#################################

### CHANGE: added new imports os and urllib, see below
import cssutils
import os
import sys
import urllib
parser=cssutils.CSSParser()

#Omit comments
cssutils.ser.prefs.keepComments = False



# class cssutils.css.CSSRuleList(*ignored)
#
#
def checkrules(sheet):

### CHANGE: simplified
for rule in sheet.cssRules: #class cssutils.css.CSSRule

if rule.type == rule.STYLE_RULE:
print rule.selectorText, "{"
for property in rule.style:
print "\t",property.name, " \t:",
print "\t",property.value
if property.valid:
pass
else:
print "Invalid property"
sys.exit(2)
if rule.type == rule.IMPORT_RULE:

## CHANGE: this @imports href is relative to the
containing stylesheet (which href is the one given via parseString
(..., href) or the one parseFile finds automatically) and you can and
probable should use a relative path here. But why do you change the
href of the @import here anyway?
imp=cssutils.css.CSSImportRule(href="sheets/import.css")

print "import ", imp.href
print "}"
print "\t\t-----"



#print property cssutils.css.Property
#print rule.type, rule.typeString,
#print rule.cssText


#
# Check a list of stylesheets
#
def ckSS(list):
for item in list:
parser=cssutils.CSSParser() #return a DOM Level 2 CSS
StyleSheet object

### CHANGE: removed explicit encoding, UTF-8 is default or
encoding is found from sheet (if e.g. @charset)
sheet = parser.parseFile(item)

# returns
#class
cssutils.css.CSSStyleSheet
print "******************* Checking %s
**********************" % item

### WHY do you do this?
text= sheet.cssText

### CHANGE: Finding absolute URL to item, in this case file:
URL, I don't know a simpler version unfortunately but if you use files
parseFile is much easier as above.
sheethref = 'file:' + urllib.pathname2url(os.path.abspath
(item))

### Why do you parse text twice anyway?
parsedText=parser.parseString(text, href=sheethref)# returns
cssutils.css.CSSStyleSheet

checkrules(sheet)
#
# List of stylesheets
#
ssList=['sheets/import.css']

ckSS(ssList)
Reply all
Reply to author
Forward
0 new messages