Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/soupsieve/__init__.py: 68%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2Soup Sieve.
4A CSS selector filter for BeautifulSoup4.
6MIT License
8Copyright (c) 2018 Isaac Muse
10Permission is hereby granted, free of charge, to any person obtaining a copy
11of this software and associated documentation files (the "Software"), to deal
12in the Software without restriction, including without limitation the rights
13to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14copies of the Software, and to permit persons to whom the Software is
15furnished to do so, subject to the following conditions:
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26SOFTWARE.
27"""
28from __future__ import annotations
29from .__meta__ import __version__, __version_info__ # noqa: F401
30from . import css_parser as cp
31from . import css_match as cm
32from . import css_types as ct
33from .util import DEBUG, NOCACHE, NOSTRICT, SelectorSyntaxError # noqa: F401
34import bs4
35from typing import Any, Mapping, Iterator, Iterable, cast
37__all__ = (
38 'DEBUG', 'NOCACHE', 'NOSTRICT', 'SelectorSyntaxError', 'CustomSelectors', 'SoupSieve',
39 'closest', 'compile', 'filter', 'iselect', 'match', 'select', 'select_one'
40)
42SoupSieve = cm.SoupSieve
43CustomSelectors = ct.CustomSelectors
46def compile( # noqa: A001
47 pattern: str,
48 namespaces: dict[str, str] | None = None,
49 flags: int = 0,
50 *,
51 custom: Mapping[str, str | ct.SelectorList] | None = None,
52 ignore: Iterable[str] | None = None,
53 max_selectors: int = cp.SELECTOR_LIMIT,
54 **kwargs: Any
55) -> cm.SoupSieve:
56 """Compile CSS pattern."""
58 if isinstance(pattern, SoupSieve):
59 if flags:
60 raise ValueError("Cannot process 'flags' argument on a compiled selector list")
61 elif namespaces is not None:
62 raise ValueError("Cannot process 'namespaces' argument on a compiled selector list")
63 elif custom is not None:
64 raise ValueError("Cannot process 'custom' argument on a compiled selector list")
65 return pattern
67 return cp._cached_css_compile(
68 pattern,
69 ct.Namespaces(namespaces) if namespaces is not None else namespaces,
70 ct.CustomSelectors(
71 cast('dict[str, str | ct.SelectorList]', custom), max_selectors=max_selectors
72 ) if custom is not None and not isinstance(custom, ct.CustomSelectors) else custom,
73 tuple(i.lower() for i in ignore) if ignore is not None else ignore,
74 flags,
75 max_selectors
76 )
79def purge() -> None:
80 """Purge cached patterns."""
82 cp._purge_cache()
85def closest(
86 select: str,
87 tag: bs4.Tag,
88 namespaces: dict[str, str] | None = None,
89 flags: int = 0,
90 *,
91 custom: Mapping[str, str | ct.SelectorList] | None = None,
92 ignore: Iterable[str] | None = None,
93 max_selectors: int = cp.SELECTOR_LIMIT,
94 **kwargs: Any
95) -> bs4.Tag | None:
96 """Match closest ancestor."""
98 return compile(
99 select,
100 namespaces,
101 flags,
102 custom=custom,
103 ignore=ignore,
104 max_selectors=max_selectors,
105 **kwargs
106 ).closest(tag)
109def match(
110 select: str,
111 tag: bs4.Tag,
112 namespaces: dict[str, str] | None = None,
113 flags: int = 0,
114 *,
115 custom: Mapping[str, str | ct.SelectorList] | None = None,
116 ignore: Iterable[str] | None = None,
117 max_selectors: int = cp.SELECTOR_LIMIT,
118 **kwargs: Any
119) -> bool:
120 """Match node."""
122 return compile(
123 select,
124 namespaces,
125 flags,
126 custom=custom,
127 ignore=ignore,
128 max_selectors=max_selectors,
129 **kwargs
130 ).match(tag)
133def filter( # noqa: A001
134 select: str,
135 iterable: Iterable[bs4.Tag],
136 namespaces: dict[str, str] | None = None,
137 flags: int = 0,
138 *,
139 custom: Mapping[str, str | ct.SelectorList] | None = None,
140 ignore: Iterable[str] | None = None,
141 max_selectors: int = cp.SELECTOR_LIMIT,
142 **kwargs: Any
143) -> list[bs4.Tag]:
144 """Filter list of nodes."""
146 return compile(
147 select,
148 namespaces,
149 flags,
150 custom=custom,
151 ignore=ignore,
152 max_selectors=max_selectors,
153 **kwargs
154 ).filter(iterable)
157def select_one(
158 select: str,
159 tag: bs4.Tag,
160 namespaces: dict[str, str] | None = None,
161 flags: int = 0,
162 *,
163 custom: Mapping[str, str | ct.SelectorList] | None = None,
164 ignore: Iterable[str] | None = None,
165 max_selectors: int = cp.SELECTOR_LIMIT,
166 **kwargs: Any
167) -> bs4.Tag | None:
168 """Select a single tag."""
170 return compile(
171 select,
172 namespaces,
173 flags,
174 custom=custom,
175 ignore=ignore,
176 max_selectors=max_selectors,
177 **kwargs
178 ).select_one(tag)
181def select(
182 select: str,
183 tag: bs4.Tag,
184 namespaces: dict[str, str] | None = None,
185 limit: int = 0,
186 flags: int = 0,
187 *,
188 custom: Mapping[str, str | ct.SelectorList] | None = None,
189 ignore: Iterable[str] | None = None,
190 max_selectors: int = cp.SELECTOR_LIMIT,
191 **kwargs: Any
192) -> list[bs4.Tag]:
193 """Select the specified tags."""
195 return compile(
196 select,
197 namespaces,
198 flags,
199 custom=custom,
200 ignore=ignore,
201 max_selectors=max_selectors,
202 **kwargs
203 ).select(tag, limit)
206def iselect(
207 select: str,
208 tag: bs4.Tag,
209 namespaces: dict[str, str] | None = None,
210 limit: int = 0,
211 flags: int = 0,
212 *,
213 custom: Mapping[str, str | ct.SelectorList] | None = None,
214 ignore: Iterable[str] | None = None,
215 max_selectors: int = cp.SELECTOR_LIMIT,
216 **kwargs: Any
217) -> Iterator[bs4.Tag]:
218 """Iterate the specified tags."""
220 yield from compile(
221 select,
222 namespaces,
223 flags,
224 custom=custom,
225 ignore=ignore,
226 max_selectors=max_selectors,
227 **kwargs
228 ).iselect(tag, limit)
231def escape(ident: str) -> str:
232 """Escape identifier."""
234 return cp.escape(ident)