Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/soupsieve/__init__.py: 70%

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

34import bs4 

35from typing import Any, Iterator, Iterable 

36 

37__all__ = ( 

38 'DEBUG', '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 **kwargs: Any 

53) -> cm.SoupSieve: 

54 """Compile CSS pattern.""" 

55 

56 if isinstance(pattern, SoupSieve): 

57 if flags: 

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

59 elif namespaces is not None: 

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

61 elif custom is not None: 

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

63 return pattern 

64 

65 return cp._cached_css_compile( 

66 pattern, 

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

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

69 flags 

70 ) 

71 

72 

73def purge() -> None: 

74 """Purge cached patterns.""" 

75 

76 cp._purge_cache() 

77 

78 

79def closest( 

80 select: str, 

81 tag: bs4.Tag, 

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

83 flags: int = 0, 

84 *, 

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

86 **kwargs: Any 

87) -> bs4.Tag | None: 

88 """Match closest ancestor.""" 

89 

90 return compile(select, namespaces, flags, **kwargs).closest(tag) 

91 

92 

93def match( 

94 select: str, 

95 tag: bs4.Tag, 

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

97 flags: int = 0, 

98 *, 

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

100 **kwargs: Any 

101) -> bool: 

102 """Match node.""" 

103 

104 return compile(select, namespaces, flags, **kwargs).match(tag) 

105 

106 

107def filter( # noqa: A001 

108 select: str, 

109 iterable: Iterable[bs4.Tag], 

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

111 flags: int = 0, 

112 *, 

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

114 **kwargs: Any 

115) -> list[bs4.Tag]: 

116 """Filter list of nodes.""" 

117 

118 return compile(select, namespaces, flags, **kwargs).filter(iterable) 

119 

120 

121def select_one( 

122 select: str, 

123 tag: bs4.Tag, 

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

125 flags: int = 0, 

126 *, 

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

128 **kwargs: Any 

129) -> bs4.Tag | None: 

130 """Select a single tag.""" 

131 

132 return compile(select, namespaces, flags, **kwargs).select_one(tag) 

133 

134 

135def select( 

136 select: str, 

137 tag: bs4.Tag, 

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

139 limit: int = 0, 

140 flags: int = 0, 

141 *, 

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

143 **kwargs: Any 

144) -> list[bs4.Tag]: 

145 """Select the specified tags.""" 

146 

147 return compile(select, namespaces, flags, **kwargs).select(tag, limit) 

148 

149 

150def iselect( 

151 select: str, 

152 tag: bs4.Tag, 

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

154 limit: int = 0, 

155 flags: int = 0, 

156 *, 

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

158 **kwargs: Any 

159) -> Iterator[bs4.Tag]: 

160 """Iterate the specified tags.""" 

161 

162 yield from compile(select, namespaces, flags, **kwargs).iselect(tag, limit) 

163 

164 

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

166 """Escape identifier.""" 

167 

168 return cp.escape(ident)