Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
30b6089
commit 2abff64
Showing
4 changed files
with
201 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
""" | ||
Format a pretty string of a `SoupSieve` object for easy debugging. | ||
This won't necessarily support all types and such, and definitely | ||
not support custom outputs. | ||
It is mainly geared towards our types as the `SelectorList` | ||
object is a beast to look at without some indentation and newlines. | ||
The format and various output types is fairly known (though it | ||
hasn't been tested extensively to make sure we aren't missing corners). | ||
Example: | ||
``` | ||
>>> import soupsieve as sv | ||
>>> sv.compile('this > that.class[name=value]').selectors.pretty() | ||
SelectorList( | ||
selectors=( | ||
Selector( | ||
tag=SelectorTag( | ||
name='that', | ||
prefix=None), | ||
ids=(), | ||
classes=( | ||
'class', | ||
), | ||
attributes=( | ||
SelectorAttribute( | ||
attribute='name', | ||
prefix='', | ||
pattern=re.compile( | ||
'^value$'), | ||
xml_type_pattern=None), | ||
), | ||
nth=(), | ||
selectors=(), | ||
relation=SelectorList( | ||
selectors=( | ||
Selector( | ||
tag=SelectorTag( | ||
name='this', | ||
prefix=None), | ||
ids=(), | ||
classes=(), | ||
attributes=(), | ||
nth=(), | ||
selectors=(), | ||
relation=SelectorList( | ||
selectors=(), | ||
is_not=False, | ||
is_html=False), | ||
rel_type='>', | ||
contains=(), | ||
lang=(), | ||
flags=0), | ||
), | ||
is_not=False, | ||
is_html=False), | ||
rel_type=None, | ||
contains=(), | ||
lang=(), | ||
flags=0), | ||
), | ||
is_not=False, | ||
is_html=False) | ||
``` | ||
""" | ||
import re | ||
|
||
RE_CLASS = re.compile(r'(?i)[a-z_][_a-z\d\.]+\(') | ||
RE_PARAM = re.compile(r'(?i)[_a-z][_a-z\d]+=') | ||
RE_EMPTY = re.compile(r'\(\)|\[\]|\{\}') | ||
RE_LSTRT = re.compile(r'\[') | ||
RE_DSTRT = re.compile(r'\{') | ||
RE_TSTRT = re.compile(r'\(') | ||
RE_LEND = re.compile(r'\]') | ||
RE_DEND = re.compile(r'\}') | ||
RE_TEND = re.compile(r'\)') | ||
RE_INT = re.compile(r'\d+') | ||
RE_KWORD = re.compile(r'(?i)[_a-z][_a-z\d]+') | ||
RE_DQSTR = re.compile(r'"(?:\\.|[^"\\])*"') | ||
RE_SQSTR = re.compile(r"'(?:\\.|[^'\\])*'") | ||
RE_SEP = re.compile(r'\s*(,)\s*') | ||
RE_DSEP = re.compile(r'\s*(:)\s*') | ||
|
||
TOKENS = { | ||
'class': RE_CLASS, | ||
'param': RE_PARAM, | ||
'empty': RE_EMPTY, | ||
'lstrt': RE_LSTRT, | ||
'dstrt': RE_DSTRT, | ||
'tstrt': RE_TSTRT, | ||
'lend': RE_LEND, | ||
'dend': RE_DEND, | ||
'tend': RE_TEND, | ||
'sqstr': RE_SQSTR, | ||
'sep': RE_SEP, | ||
'dsep': RE_DSEP, | ||
'int': RE_INT, | ||
'kword': RE_KWORD, | ||
'dqstr': RE_DQSTR | ||
} | ||
|
||
|
||
def pretty(obj): # pragma: no cover | ||
"""Make the object output string pretty.""" | ||
|
||
sel = str(obj) | ||
index = 0 | ||
end = len(sel) - 1 | ||
indent = 0 | ||
output = [] | ||
|
||
while index <= end: | ||
m = None | ||
for k, v in TOKENS.items(): | ||
m = v.match(sel, index) | ||
|
||
if m: | ||
name = k | ||
index = m.end(0) | ||
if name in ('class', 'lstrt', 'dstrt', 'tstrt'): | ||
indent += 4 | ||
output.append('{}\n{}'.format(m.group(0), " " * indent)) | ||
elif name in ('param', 'int', 'kword', 'sqstr', 'dqstr', 'empty'): | ||
output.append(m.group(0)) | ||
elif name in ('lend', 'dend', 'tend'): | ||
indent -= 4 | ||
output.append(m.group(0)) | ||
elif name in ('sep',): | ||
output.append('{}\n{}'.format(m.group(1), " " * indent)) | ||
elif name in ('dsep',): | ||
output.append('{} '.format(m.group(1))) | ||
break | ||
|
||
return ''.join(output) |