1 """CSSCharsetRule implements DOM Level 2 CSS CSSCharsetRule.
2
3 TODO:
4 - check specific allowed syntaxes
5 - check encoding syntax and not codecs.lookup?
6 """
7 __all__ = ['CSSCharsetRule']
8 __docformat__ = 'restructuredtext'
9 __author__ = '$LastChangedBy: cthedot $'
10 __date__ = '$LastChangedDate: 2007-10-20 20:05:47 +0200 (Sa, 20 Okt 2007) $'
11 __version__ = '$LastChangedRevision: 541 $'
12
13 import codecs
14 import xml.dom
15 import cssrule
16 import cssutils
17
19 """
20 The CSSCharsetRule interface represents an @charset rule in a CSS style
21 sheet. The value of the encoding attribute does not affect the encoding
22 of text data in the DOM objects; this encoding is always UTF-16
23 (also in Python?). After a stylesheet is loaded, the value of the
24 encoding attribute is the value found in the @charset rule. If there
25 was no @charset in the original document, then no CSSCharsetRule is
26 created. The value of the encoding attribute may also be used as a hint
27 for the encoding used on serialization of the style sheet.
28
29 The value of the @charset rule (and therefore of the CSSCharsetRule)
30 may not correspond to the encoding the document actually came in;
31 character encoding information e.g. in an HTTP header, has priority
32 (see CSS document representation) but this is not reflected in the
33 CSSCharsetRule.
34
35 Properties
36 ==========
37 cssText: of type DOMString
38 The parsable textual representation of this rule
39 encoding: of type DOMString
40 The encoding information used in this @charset rule.
41
42 Inherits properties from CSSRule
43
44 Format
45 ======
46 charsetrule:
47 CHARSET_SYM S* STRING S* ';'
48
49 BUT: Only valid format is:
50 @charset "ENCODING";
51 """
52 type = cssrule.CSSRule.CHARSET_RULE
53
54 - def __init__(self, encoding=None, readonly=False):
55 """
56 encoding:
57 a valid character encoding
58 readonly:
59 defaults to False, not used yet
60
61 if readonly allows setting of properties in constructor only
62 """
63 super(CSSCharsetRule, self).__init__()
64
65 self._encoding = None
66 if encoding:
67 self.encoding = encoding
68
69 self._readonly = readonly
70
72 """ returns encoding as a string """
73 return self._encoding
74
76 """
77 DOMException on setting
78
79 - NO_MODIFICATION_ALLOWED_ERR: (CSSRule)
80 Raised if this encoding rule is readonly.
81 - SYNTAX_ERR: (self)
82 Raised if the specified encoding value has a syntax error and
83 is unparsable.
84 Currently only valid Python encodings are allowed.
85 """
86 self._checkReadonly()
87 tokenizer = self._tokenize2(encoding)
88 encodingtoken = self._nexttoken(tokenizer)
89 unexpected = self._nexttoken(tokenizer)
90
91 valid = True
92 if not encodingtoken or unexpected or\
93 self._prods.IDENT != self._type(encodingtoken):
94 valid = False
95 self._log.error(
96 'CSSCharsetRule: Syntax Error in encoding value %r.' %
97 encoding)
98 else:
99 try:
100 codecs.lookup(encoding)
101 except LookupError:
102 valid = False
103 self._log.error('CSSCharsetRule: Unknown (Python) encoding %r.' %
104 encoding)
105 else:
106 self._encoding = encoding.lower()
107 self.valid = valid
108
109 encoding = property(_getEncoding, _setEncoding,
110 doc="(DOM)The encoding information used in this @charset rule.")
111
112
113 - def _getCssText(self):
114 """returns serialized property cssText"""
115 return cssutils.ser.do_CSSCharsetRule(self)
116
117 - def _setCssText(self, cssText):
118 """
119 DOMException on setting
120
121 - SYNTAX_ERR: (self)
122 Raised if the specified CSS string value has a syntax error and
123 is unparsable.
124 - INVALID_MODIFICATION_ERR: (self)
125 Raised if the specified CSS string value represents a different
126 type of rule than the current one.
127 - HIERARCHY_REQUEST_ERR: (CSSStylesheet)
128 Raised if the rule cannot be inserted at this point in the
129 style sheet.
130 - NO_MODIFICATION_ALLOWED_ERR: (CSSRule)
131 Raised if the rule is readonly.
132 """
133 super(CSSCharsetRule, self)._setCssText(cssText)
134
135 valid = True
136 tokenizer = self._tokenize2(cssText)
137
138 atkeyword = self._tokenvalue(self._nexttoken(tokenizer))
139 if u'@charset ' != atkeyword:
140 valid = False
141 self._log.error(u'CSSCharsetRule must start with "@charset "',
142 error=xml.dom.InvalidModificationErr)
143
144 encodingtoken = self._nexttoken(tokenizer)
145 encodingtype, encoding = self._type(encodingtoken), self._tokenvalue(
146 encodingtoken)
147 if 'STRING' != encodingtype or len(encoding) < 3:
148 valid = False
149 self._log.error(u'CSSCharsetRule: no encoding found.')
150 else:
151 encoding = encoding[1:-1]
152
153 semicolon = self._tokenvalue(self._nexttoken(tokenizer))
154 EOFtype = self._type(self._nexttoken(tokenizer))
155 if u';' != semicolon or (EOFtype and 'EOF' != EOFtype):
156 valid = False
157 self._log.error(u'CSSCharsetRule: Syntax Error: %r.' %
158 self._valuestr(cssText))
159
160 self.valid = valid
161 if valid:
162 self.encoding = encoding
163
164 cssText = property(fget=_getCssText, fset=_setCssText,
165 doc="(DOM) The parsable textual representation.")
166
168 return "cssutils.css.%s(encoding=%r)" % (
169 self.__class__.__name__, self.encoding)
170
172 return "<cssutils.css.%s object encoding=%r at 0x%x>" % (
173 self.__class__.__name__, self.encoding, id(self))
174