selectolax 0.3.24__cp311-cp311-musllinux_1_2_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of selectolax might be problematic. Click here for more details.

@@ -0,0 +1,182 @@
1
+ cimport cython
2
+
3
+ @cython.final
4
+ cdef class LexborCSSSelector:
5
+
6
+ def __init__(self):
7
+ self._create_css_parser()
8
+ self.results = []
9
+ self.current_node = None
10
+
11
+ cdef _create_css_parser(self):
12
+ cdef lxb_status_t status
13
+
14
+
15
+ self.parser = lxb_css_parser_create()
16
+ status = lxb_css_parser_init(self.parser, NULL)
17
+
18
+ if status != LXB_STATUS_OK:
19
+ raise SelectolaxError("Can't initialize CSS parser.")
20
+
21
+ self.css_selectors = lxb_css_selectors_create()
22
+ status = lxb_css_selectors_init(self.css_selectors)
23
+
24
+ if status != LXB_STATUS_OK:
25
+ raise SelectolaxError("Can't initialize CSS selector.")
26
+
27
+ lxb_css_parser_selectors_set(self.parser, self.css_selectors)
28
+
29
+ self.selectors = lxb_selectors_create()
30
+ status = lxb_selectors_init(self.selectors)
31
+ lxb_selectors_opt_set(self.selectors, LXB_SELECTORS_OPT_MATCH_ROOT)
32
+ if status != LXB_STATUS_OK:
33
+ raise SelectolaxError("Can't initialize CSS selector.")
34
+
35
+
36
+ cpdef find(self, str query, LexborNode node):
37
+ cdef lxb_css_selector_list_t* selectors
38
+ cdef lxb_char_t* c_selector
39
+ cdef lxb_css_selector_list_t * selectors_list
40
+
41
+ bytes_query = query.encode(_ENCODING)
42
+ selectors_list = lxb_css_selectors_parse(self.parser, <lxb_char_t *> bytes_query, <size_t>len(query))
43
+
44
+ if selectors_list == NULL:
45
+ raise SelectolaxError("Can't parse CSS selector.")
46
+
47
+ self.current_node = node
48
+ self.results = []
49
+ status = lxb_selectors_find(self.selectors, node.node, selectors_list,
50
+ <lxb_selectors_cb_f>css_finder_callback, <void*>self)
51
+ results = list(self.results)
52
+ self.results = []
53
+ self.current_node = None
54
+ lxb_css_selector_list_destroy_memory(selectors_list)
55
+ return results
56
+
57
+ cpdef any_matches(self, str query, LexborNode node):
58
+ cdef lxb_css_selector_list_t * selectors
59
+ cdef lxb_char_t * c_selector
60
+ cdef lxb_css_selector_list_t * selectors_list
61
+
62
+ bytes_query = query.encode(_ENCODING)
63
+ selectors_list = lxb_css_selectors_parse(self.parser, <lxb_char_t *> bytes_query, <size_t> len(query))
64
+
65
+ if selectors_list == NULL:
66
+ raise SelectolaxError("Can't parse CSS selector.")
67
+
68
+ self.results = []
69
+ status = lxb_selectors_find(self.selectors, node.node, selectors_list,
70
+ <lxb_selectors_cb_f> css_matcher_callback, <void *> self)
71
+ if status != LXB_STATUS_OK:
72
+ raise SelectolaxError("Can't parse CSS selector.")
73
+ result = bool(self.results)
74
+ self.results = []
75
+ lxb_css_selector_list_destroy_memory(selectors_list)
76
+ return result
77
+
78
+
79
+ def __dealloc__(self):
80
+ lxb_selectors_destroy(self.selectors, True)
81
+ # lxb_css_memory_destroy(self.parser.memory, True)
82
+ lxb_css_parser_destroy(self.parser, True)
83
+ lxb_css_selectors_destroy(self.css_selectors, True)
84
+
85
+
86
+
87
+ cdef class LexborSelector:
88
+ """An advanced CSS selector that supports additional operations.
89
+
90
+ Think of it as a toolkit that mimics some of the features of XPath.
91
+
92
+ Please note, this is an experimental feature that can change in the future.
93
+ """
94
+ cdef LexborNode node
95
+ cdef list nodes
96
+
97
+ def __init__(self, LexborNode node, query):
98
+ self.node = node
99
+ self.nodes = self.node.parser.selector.find(query, self.node) if query else [node, ]
100
+
101
+
102
+ cpdef css(self, str query):
103
+ """Evaluate CSS selector against current scope."""
104
+ raise SelectolaxError("This features is not supported by the lexbor backend. Please use Modest backend.")
105
+
106
+ @property
107
+ def matches(self):
108
+ """Returns all possible matches"""
109
+ return self.nodes
110
+
111
+ @property
112
+ def any_matches(self):
113
+ """Returns True if there are any matches"""
114
+ return bool(self.nodes)
115
+
116
+ def text_contains(self, str text, bool deep=True, str separator='', bool strip=False):
117
+ """Filter all current matches given text."""
118
+ nodes = []
119
+ for node in self.nodes:
120
+ node_text = node.text(deep=deep, separator=separator, strip=strip)
121
+ if node_text and text in node_text:
122
+ nodes.append(node)
123
+ self.nodes = nodes
124
+ return self
125
+
126
+ def any_text_contains(self, str text, bool deep=True, str separator='', bool strip=False):
127
+ """Returns True if any node in the current search scope contains specified text"""
128
+ nodes = []
129
+ for node in self.nodes:
130
+ node_text = node.text(deep=deep, separator=separator, strip=strip)
131
+ if node_text and text in node_text:
132
+ return True
133
+ return False
134
+
135
+ def attribute_longer_than(self, str attribute, int length, str start = None):
136
+ """Filter all current matches by attribute length.
137
+
138
+ Similar to `string-length` in XPath.
139
+ """
140
+ nodes = []
141
+ for node in self.nodes:
142
+ attr = node.attributes.get(attribute)
143
+ if attr and start and start in attr:
144
+ attr = attr[attr.find(start) + len(start):]
145
+ if len(attr) > length:
146
+ nodes.append(node)
147
+ self.nodes = nodes
148
+ return self
149
+
150
+ def any_attribute_longer_than(self, str attribute, int length, str start = None):
151
+ """Returns True any href attribute longer than a specified length.
152
+
153
+ Similar to `string-length` in XPath.
154
+ """
155
+ nodes = []
156
+ for node in self.nodes:
157
+ attr = node.attributes.get(attribute)
158
+ if attr and start and start in attr:
159
+ attr = attr[attr.find(start) + len(start):]
160
+ if len(attr) > length:
161
+ return True
162
+ return False
163
+
164
+ def __bool__(self):
165
+ return bool(self.nodes)
166
+
167
+
168
+ cdef lxb_status_t css_finder_callback(lxb_dom_node_t *node, lxb_css_selector_specificity_t *spec, void *ctx):
169
+ cdef LexborNode lxb_node
170
+ cdef object cls
171
+ cls = <object> ctx
172
+ lxb_node = LexborNode()
173
+ lxb_node._cinit(<lxb_dom_node_t *> node, cls.current_node.parser)
174
+ cls.results.append(lxb_node)
175
+ return LXB_STATUS_OK
176
+
177
+ cdef lxb_status_t css_matcher_callback(lxb_dom_node_t *node, lxb_css_selector_specificity_t *spec, void *ctx):
178
+ cdef LexborNode lxb_node
179
+ cdef object cls
180
+ cls = <object> ctx
181
+ cls.results.append(True)
182
+ return LXB_STATUS_STOP