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

37 statements  

1""" 

2Soup Sieve. 

3 

4A CSS selector filter for BeautifulSoup4. 

5 

6MIT License 

7 

8Copyright (c) 2018 Isaac Muse 

9 

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: 

16 

17The above copyright notice and this permission notice shall be included in all 

18copies or substantial portions of the Software. 

19 

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, SelectorSyntaxError # noqa: F401 

34import bs4 

35from typing import Any, Iterator, Iterable 

36 

37__all__ = ( 

38 'DEBUG', 'NOCACHE', 'SelectorSyntaxError', 'SoupSieve', 

39 'closest', 'compile', 'filter', 'iselect', 

40 'match', 'select', 'select_one' 

41) 

42 

43SoupSieve = cm.SoupSieve 

44 

45 

46def compile( # noqa: A001 

47 pattern: str, 

48 namespaces: dict[str, str] | None = None, 

49 flags: int = 0, 

50 *, 

51 custom: dict[str, str] | None = None, 

52 ignore: Iterable[str] | None = None, 

53 **kwargs: Any 

54) -> cm.SoupSieve: 

55 """Compile CSS pattern.""" 

56 

57 if isinstance(pattern, SoupSieve): 

58 if flags: 

59 raise ValueError("Cannot process 'flags' argument on a compiled selector list") 

60 elif namespaces is not None: 

61 raise ValueError("Cannot process 'namespaces' argument on a compiled selector list") 

62 elif custom is not None: 

63 raise ValueError("Cannot process 'custom' argument on a compiled selector list") 

64 return pattern 

65 

66 return cp._cached_css_compile( 

67 pattern, 

68 ct.Namespaces(namespaces) if namespaces is not None else namespaces, 

69 ct.CustomSelectors(custom) if custom is not None else custom, 

70 tuple(i.lower() for i in ignore) if ignore is not None else ignore, 

71 flags, 

72 ) 

73 

74 

75def purge() -> None: 

76 """Purge cached patterns.""" 

77 

78 cp._purge_cache() 

79 

80 

81def closest( 

82 select: str, 

83 tag: bs4.Tag, 

84 namespaces: dict[str, str] | None = None, 

85 flags: int = 0, 

86 *, 

87 custom: dict[str, str] | None = None, 

88 ignore: Iterable[str] | None = None, 

89 **kwargs: Any 

90) -> bs4.Tag | None: 

91 """Match closest ancestor.""" 

92 

93 return compile(select, namespaces, flags, custom=custom, ignore=ignore, **kwargs).closest(tag) 

94 

95 

96def match( 

97 select: str, 

98 tag: bs4.Tag, 

99 namespaces: dict[str, str] | None = None, 

100 flags: int = 0, 

101 *, 

102 custom: dict[str, str] | None = None, 

103 ignore: Iterable[str] | None = None, 

104 **kwargs: Any 

105) -> bool: 

106 """Match node.""" 

107 

108 return compile(select, namespaces, flags, custom=custom, ignore=ignore, **kwargs).match(tag) 

109 

110 

111def filter( # noqa: A001 

112 select: str, 

113 iterable: Iterable[bs4.Tag], 

114 namespaces: dict[str, str] | None = None, 

115 flags: int = 0, 

116 *, 

117 custom: dict[str, str] | None = None, 

118 ignore: Iterable[str] | None = None, 

119 **kwargs: Any 

120) -> list[bs4.Tag]: 

121 """Filter list of nodes.""" 

122 

123 return compile(select, namespaces, flags, custom=custom, ignore=ignore, **kwargs).filter(iterable) 

124 

125 

126def select_one( 

127 select: str, 

128 tag: bs4.Tag, 

129 namespaces: dict[str, str] | None = None, 

130 flags: int = 0, 

131 *, 

132 custom: dict[str, str] | None = None, 

133 ignore: Iterable[str] | None = None, 

134 **kwargs: Any 

135) -> bs4.Tag | None: 

136 """Select a single tag.""" 

137 

138 return compile(select, namespaces, flags, custom=custom, ignore=ignore, **kwargs).select_one(tag) 

139 

140 

141def select( 

142 select: str, 

143 tag: bs4.Tag, 

144 namespaces: dict[str, str] | None = None, 

145 limit: int = 0, 

146 flags: int = 0, 

147 *, 

148 custom: dict[str, str] | None = None, 

149 ignore: Iterable[str] | None = None, 

150 **kwargs: Any 

151) -> list[bs4.Tag]: 

152 """Select the specified tags.""" 

153 

154 return compile(select, namespaces, flags, custom=custom, ignore=ignore, **kwargs).select(tag, limit) 

155 

156 

157def iselect( 

158 select: str, 

159 tag: bs4.Tag, 

160 namespaces: dict[str, str] | None = None, 

161 limit: int = 0, 

162 flags: int = 0, 

163 *, 

164 custom: dict[str, str] | None = None, 

165 ignore: Iterable[str] | None = None, 

166 **kwargs: Any 

167) -> Iterator[bs4.Tag]: 

168 """Iterate the specified tags.""" 

169 

170 yield from compile(select, namespaces, flags, custom=custom, ignore=ignore, **kwargs).iselect(tag, limit) 

171 

172 

173def escape(ident: str) -> str: 

174 """Escape identifier.""" 

175 

176 return cp.escape(ident)