Skip to content

Commit 8d0ff3e

Browse files
committed
rename method to .canonical, and correctly strip extra * in :not selectors (otherwise edge ignores them)
1 parent 4e90061 commit 8d0ff3e

File tree

3 files changed

+35
-27
lines changed

3 files changed

+35
-27
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ Simon Sapin
1010
Stefan Behnel
1111
Thomas Grainger
1212
Varialus
13+
Arthur Darcet

cssselect/parser.py

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,16 @@ def __repr__(self):
9292
return '%s[%r%s]' % (
9393
self.__class__.__name__, self.parsed_tree, pseudo_element)
9494

95-
def css(self):
95+
def canonical(self):
9696
"""Return a CSS representation for this selector (a string)
9797
"""
9898
if isinstance(self.pseudo_element, FunctionalPseudoElement):
99-
pseudo_element = '::%s' % self.pseudo_element.css()
99+
pseudo_element = '::%s' % self.pseudo_element.canonical()
100100
elif self.pseudo_element:
101101
pseudo_element = '::%s' % self.pseudo_element
102102
else:
103103
pseudo_element = ''
104-
res = '%s%s' % (self.parsed_tree.css(), pseudo_element)
104+
res = '%s%s' % (self.parsed_tree.canonical(), pseudo_element)
105105
if len(res) > 1:
106106
res = res.lstrip('*')
107107
return res
@@ -130,8 +130,8 @@ def __repr__(self):
130130
return '%s[%r.%s]' % (
131131
self.__class__.__name__, self.selector, self.class_name)
132132

133-
def css(self):
134-
return '%s.%s' % (self.selector.css(), self.class_name)
133+
def canonical(self):
134+
return '%s.%s' % (self.selector.canonical(), self.class_name)
135135

136136
def specificity(self):
137137
a, b, c = self.selector.specificity()
@@ -168,7 +168,7 @@ def __repr__(self):
168168
def argument_types(self):
169169
return [token.type for token in self.arguments]
170170

171-
def css(self):
171+
def canonical(self):
172172
args = ''.join(token.css() for token in self.arguments)
173173
return '%s(%s)' % (self.name, args)
174174

@@ -195,9 +195,9 @@ def __repr__(self):
195195
def argument_types(self):
196196
return [token.type for token in self.arguments]
197197

198-
def css(self):
198+
def canonical(self):
199199
args = ''.join(token.css() for token in self.arguments)
200-
return '%s:%s(%s)' % (self.selector.css(), self.name, args)
200+
return '%s:%s(%s)' % (self.selector.canonical(), self.name, args)
201201

202202
def specificity(self):
203203
a, b, c = self.selector.specificity()
@@ -217,8 +217,8 @@ def __repr__(self):
217217
return '%s[%r:%s]' % (
218218
self.__class__.__name__, self.selector, self.ident)
219219

220-
def css(self):
221-
return '%s:%s' % (self.selector.css(), self.ident)
220+
def canonical(self):
221+
return '%s:%s' % (self.selector.canonical(), self.ident)
222222

223223
def specificity(self):
224224
a, b, c = self.selector.specificity()
@@ -238,9 +238,11 @@ def __repr__(self):
238238
return '%s[%r:not(%r)]' % (
239239
self.__class__.__name__, self.selector, self.subselector)
240240

241-
def css(self):
242-
return '%s:not(%s)' % (self.selector.css(),
243-
self.subselector.css())
241+
def canonical(self):
242+
subsel = self.subselector.canonical()
243+
if len(subsel) > 1:
244+
subsel = subsel.lstrip('*')
245+
return '%s:not(%s)' % (self.selector.canonical(), subsel)
244246

245247
def specificity(self):
246248
a1, b1, c1 = self.selector.specificity()
@@ -272,7 +274,7 @@ def __repr__(self):
272274
self.__class__.__name__, self.selector, attrib,
273275
self.operator, self.value.value)
274276

275-
def css(self):
277+
def canonical(self):
276278
if self.namespace:
277279
attrib = '%s|%s' % (self.namespace, self.attrib)
278280
else:
@@ -283,7 +285,7 @@ def css(self):
283285
else:
284286
op = '%s%s%s' % (attrib, self.operator, self.value.css())
285287

286-
return '%s[%s]' % (self.selector.css(), op)
288+
return '%s[%s]' % (self.selector.canonical(), op)
287289

288290
def specificity(self):
289291
a, b, c = self.selector.specificity()
@@ -303,9 +305,9 @@ def __init__(self, namespace=None, element=None):
303305
self.element = element
304306

305307
def __repr__(self):
306-
return '%s[%s]' % (self.__class__.__name__, self.css())
308+
return '%s[%s]' % (self.__class__.__name__, self.canonical())
307309

308-
def css(self):
310+
def canonical(self):
309311
element = self.element or '*'
310312
if self.namespace:
311313
element = '%s|%s' % (self.namespace, element)
@@ -330,8 +332,8 @@ def __repr__(self):
330332
return '%s[%r#%s]' % (
331333
self.__class__.__name__, self.selector, self.id)
332334

333-
def css(self):
334-
return '%s#%s' % (self.selector.css(), self.id)
335+
def canonical(self):
336+
return '%s#%s' % (self.selector.canonical(), self.id)
335337

336338
def specificity(self):
337339
a, b, c = self.selector.specificity()
@@ -354,9 +356,12 @@ def __repr__(self):
354356
return '%s[%r %s %r]' % (
355357
self.__class__.__name__, self.selector, comb, self.subselector)
356358

357-
def css(self):
358-
return '%s %s %s' % (self.selector.css(),
359-
self.combinator, self.subselector.css())
359+
def canonical(self):
360+
subsel = self.subselector.canonical()
361+
if len(subsel) > 1:
362+
subsel = subsel.lstrip('*')
363+
return '%s %s %s' % (
364+
self.selector.canonical(), self.combinator, subsel)
360365

361366
def specificity(self):
362367
a1, b1, c1 = self.selector.specificity()

tests/test_cssselect.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ def test_css_export(self):
248248
def css2css(css, res=None):
249249
selectors = parse(css)
250250
assert len(selectors) == 1
251-
assert selectors[0].css() == (res or css)
251+
assert selectors[0].canonical() == (res or css)
252252

253253
css2css('*')
254254
css2css(' foo', 'foo')
@@ -262,18 +262,20 @@ def css2css(css, res=None):
262262
css2css('[baz]')
263263
css2css('[baz="4"]', "[baz='4']")
264264
css2css('[baz^="4"]', "[baz^='4']")
265+
css2css("[ns|attr='4']")
265266
css2css('#lipsum')
266267
css2css(':not(*)')
267268
css2css(':not(foo)')
268-
css2css(':not(*.foo)')
269-
css2css(':not(*[foo])')
270-
css2css(':not(*:empty)')
271-
css2css(':not(*#foo)')
269+
css2css(':not(*.foo)', ':not(.foo)')
270+
css2css(':not(*[foo])', ':not([foo])')
271+
css2css(':not(:empty)')
272+
css2css(':not(#foo)')
272273
css2css('foo:empty')
273274
css2css('foo::before')
274275
css2css('foo:empty::before')
275276
css2css('::name(arg + "val" - 3)', "::name(arg+'val'-3)")
276277
css2css('#lorem + foo#ipsum:first-child > bar::first-line')
278+
css2css('foo > *')
277279

278280
def test_parse_errors(self):
279281
def get_error(css):

0 commit comments

Comments
 (0)