aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/soupsieve/pretty.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/soupsieve/pretty.py')
-rw-r--r--.venv/lib/python3.12/site-packages/soupsieve/pretty.py139
1 files changed, 139 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/soupsieve/pretty.py b/.venv/lib/python3.12/site-packages/soupsieve/pretty.py
new file mode 100644
index 00000000..193db05e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/soupsieve/pretty.py
@@ -0,0 +1,139 @@
+"""
+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)
+```
+
+"""
+from __future__ import annotations
+import re
+from typing import Any
+
+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: Any) -> str: # 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(f'{m.group(0)}\n{" " * 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(f'{m.group(1)}\n{" " * indent}')
+ elif name in ('dsep',):
+ output.append(f'{m.group(1)} ')
+ break
+
+ return ''.join(output)