14
14
from __future__ import annotations
15
15
16
16
import re
17
- from collections .abc import Callable
18
- from typing import TYPE_CHECKING , Optional , cast
17
+ from typing import TYPE_CHECKING , cast
19
18
20
19
from cssselect .parser import (
21
20
Attrib ,
38
37
)
39
38
40
39
if TYPE_CHECKING :
40
+ from collections .abc import Callable
41
+
41
42
# typing.Self requires Python 3.11
42
43
from typing_extensions import Self
43
44
@@ -289,7 +290,7 @@ def xpath(self, parsed_selector: Tree) -> XPathExpr:
289
290
"""Translate any parsed selector object."""
290
291
type_name = type (parsed_selector ).__name__
291
292
method = cast (
292
- Optional [ Callable [[Tree ], XPathExpr ]] ,
293
+ " Callable[[Tree], XPathExpr] | None" ,
293
294
getattr (self , f"xpath_{ type_name .lower ()} " , None ),
294
295
)
295
296
if method is None :
@@ -302,7 +303,7 @@ def xpath_combinedselector(self, combined: CombinedSelector) -> XPathExpr:
302
303
"""Translate a combined selector."""
303
304
combinator = self .combinator_mapping [combined .combinator ]
304
305
method = cast (
305
- Callable [[XPathExpr , XPathExpr ], XPathExpr ],
306
+ " Callable[[XPathExpr, XPathExpr], XPathExpr]" ,
306
307
getattr (self , f"xpath_{ combinator } _combinator" ),
307
308
)
308
309
return method (self .xpath (combined .selector ), self .xpath (combined .subselector ))
@@ -321,10 +322,10 @@ def xpath_relation(self, relation: Relation) -> XPathExpr:
321
322
subselector = relation .subselector
322
323
right = self .xpath (subselector .parsed_tree )
323
324
method = cast (
324
- Callable [[XPathExpr , XPathExpr ], XPathExpr ],
325
+ " Callable[[XPathExpr, XPathExpr], XPathExpr]" ,
325
326
getattr (
326
327
self ,
327
- f"xpath_relation_{ self .combinator_mapping [cast (str , combinator .value )]} _combinator" ,
328
+ f"xpath_relation_{ self .combinator_mapping [cast (' str' , combinator .value )]} _combinator" ,
328
329
),
329
330
)
330
331
return method (xpath , right )
@@ -351,7 +352,7 @@ def xpath_function(self, function: Function) -> XPathExpr:
351
352
"""Translate a functional pseudo-class."""
352
353
method_name = "xpath_{}_function" .format (function .name .replace ("-" , "_" ))
353
354
method = cast (
354
- Optional [ Callable [[XPathExpr , Function ], XPathExpr ]] ,
355
+ " Callable[[XPathExpr, Function], XPathExpr] | None" ,
355
356
getattr (self , method_name , None ),
356
357
)
357
358
if not method :
@@ -362,7 +363,8 @@ def xpath_pseudo(self, pseudo: Pseudo) -> XPathExpr:
362
363
"""Translate a pseudo-class."""
363
364
method_name = "xpath_{}_pseudo" .format (pseudo .ident .replace ("-" , "_" ))
364
365
method = cast (
365
- Optional [Callable [[XPathExpr ], XPathExpr ]], getattr (self , method_name , None )
366
+ "Callable[[XPathExpr], XPathExpr] | None" ,
367
+ getattr (self , method_name , None ),
366
368
)
367
369
if not method :
368
370
# TODO: better error message for pseudo-elements?
@@ -373,7 +375,7 @@ def xpath_attrib(self, selector: Attrib) -> XPathExpr:
373
375
"""Translate an attribute selector."""
374
376
operator = self .attribute_operator_mapping [selector .operator ]
375
377
method = cast (
376
- Callable [[XPathExpr , str , Optional [ str ]] , XPathExpr ],
378
+ " Callable[[XPathExpr, str, str | None] , XPathExpr]" ,
377
379
getattr (self , f"xpath_attrib_{ operator } " ),
378
380
)
379
381
if self .lower_case_attribute_names :
@@ -391,7 +393,7 @@ def xpath_attrib(self, selector: Attrib) -> XPathExpr:
391
393
if selector .value is None :
392
394
value = None
393
395
elif self .lower_case_attribute_values :
394
- value = cast (str , selector .value .value ).lower ()
396
+ value = cast (" str" , selector .value .value ).lower ()
395
397
else :
396
398
value = selector .value .value
397
399
return method (self .xpath (selector .selector ), attrib , value )
@@ -645,15 +647,15 @@ def xpath_contains_function(
645
647
raise ExpressionError (
646
648
f"Expected a single string or ident for :contains(), got { function .arguments !r} "
647
649
)
648
- value = cast (str , function .arguments [0 ].value )
650
+ value = cast (" str" , function .arguments [0 ].value )
649
651
return xpath .add_condition (f"contains(., { self .xpath_literal (value )} )" )
650
652
651
653
def xpath_lang_function (self , xpath : XPathExpr , function : Function ) -> XPathExpr :
652
654
if function .argument_types () not in (["STRING" ], ["IDENT" ]):
653
655
raise ExpressionError (
654
656
f"Expected a single string or ident for :lang(), got { function .arguments !r} "
655
657
)
656
- value = cast (str , function .arguments [0 ].value )
658
+ value = cast (" str" , function .arguments [0 ].value )
657
659
return xpath .add_condition (f"lang({ self .xpath_literal (value )} )" )
658
660
659
661
# Pseudo: dispatch by pseudo-class name
0 commit comments