blob: f70c8e39be15cb53affbe77a0dfe1db21f9d708e (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
from parsimonious.grammar import Grammar
from .. import html_paths
def read_html_path(string):
path_node = _grammar.parse(string)
return read_html_path_node(path_node)
def read_html_path_node(path_node):
if path_node.children[0].expr_name == "ignore":
return html_paths.ignore
elif path_node.children[0].children:
return _read_html_path_elements_node(path_node.children[0].children[0])
else:
return html_paths.empty
def _read_html_path_elements_node(path_node):
elements = [
_read_element_node(child)
for child in _repeated_children_with_separator(path_node, has_whitespace=True)
]
return html_paths.path(elements)
def _read_element_node(node):
tag_names = _read_tag_names_node(node.children[0])
class_names = _read_class_names_node(node.children[1])
fresh = _read_fresh_node(node.children[2])
return html_paths.element(tag_names, class_names=class_names, fresh=fresh)
def _read_tag_names_node(node):
return [
child.text
for child in _repeated_children_with_separator(node, has_whitespace=False)
]
def _read_class_names_node(class_names_node):
return [
_read_class_name_node(node)
for node in class_names_node.children
]
def _read_class_name_node(node):
return node.children[1].text
def _read_fresh_node(node):
return len(node.children) > 0
def _repeated_children_with_separator(node, has_whitespace):
yield node.children[0]
if has_whitespace:
sequence_node_index = 3
else:
sequence_node_index = 1
sequence_node = node.children[1]
for child in sequence_node.children:
yield child.children[sequence_node_index]
grammar_text = r"""
html_path = ignore / html_path_elements?
ignore = "!"
html_path_elements = element (whitespace* ">" whitespace* element)*
element = tag_names class_name* fresh?
tag_names = identifier ("|" identifier)*
class_name = "." identifier
fresh = ":fresh"
identifier = ~"[A-Z0-9]+"i
whitespace = ~"\s"*
"""
_grammar = Grammar(grammar_text)
|