comparison env/lib/python3.7/site-packages/soupsieve/util.py @ 5:9b1c78e6ba9c draft default tip

"planemo upload commit 6c0a8142489327ece472c84e558c47da711a9142"
author shellac
date Mon, 01 Jun 2020 08:59:25 -0400
parents 79f47841a781
children
comparison
equal deleted inserted replaced
4:79f47841a781 5:9b1c78e6ba9c
1 """Utility."""
2 from functools import wraps
3 import warnings
4 import os
5 import re
6 MODULE = os.path.dirname(__file__)
7
8 DEBUG = 0x00001
9
10 RE_PATTERN_LINE_SPLIT = re.compile(r'(?:\r\n|(?!\r\n)[\n\r])|$')
11
12 LC_A = ord('a')
13 LC_Z = ord('z')
14 UC_A = ord('A')
15 UC_Z = ord('Z')
16
17
18 def lower(string):
19 """Lower."""
20
21 new_string = []
22 for c in string:
23 o = ord(c)
24 new_string.append(chr(o + 32) if UC_A <= o <= UC_Z else c)
25 return ''.join(new_string)
26
27
28 def upper(string): # pragma: no cover
29 """Lower."""
30
31 new_string = []
32 for c in string:
33 o = ord(c)
34 new_string.append(chr(o - 32) if LC_A <= o <= LC_Z else c)
35 return ''.join(new_string)
36
37
38 class SelectorSyntaxError(Exception):
39 """Syntax error in a CSS selector."""
40
41 def __init__(self, msg, pattern=None, index=None):
42 """Initialize."""
43
44 self.line = None
45 self.col = None
46 self.context = None
47
48 if pattern is not None and index is not None:
49 # Format pattern to show line and column position
50 self.context, self.line, self.col = get_pattern_context(pattern, index)
51 msg = '{}\n line {}:\n{}'.format(msg, self.line, self.context)
52
53 super(SelectorSyntaxError, self).__init__(msg)
54
55
56 def deprecated(message, stacklevel=2): # pragma: no cover
57 """
58 Raise a `DeprecationWarning` when wrapped function/method is called.
59
60 Borrowed from https://stackoverflow.com/a/48632082/866026
61 """
62
63 def _decorator(func):
64 @wraps(func)
65 def _func(*args, **kwargs):
66 warnings.warn(
67 "'{}' is deprecated. {}".format(func.__name__, message),
68 category=DeprecationWarning,
69 stacklevel=stacklevel
70 )
71 return func(*args, **kwargs)
72 return _func
73 return _decorator
74
75
76 def warn_deprecated(message, stacklevel=2): # pragma: no cover
77 """Warn deprecated."""
78
79 warnings.warn(
80 message,
81 category=DeprecationWarning,
82 stacklevel=stacklevel
83 )
84
85
86 def get_pattern_context(pattern, index):
87 """Get the pattern context."""
88
89 last = 0
90 current_line = 1
91 col = 1
92 text = []
93 line = 1
94
95 # Split pattern by newline and handle the text before the newline
96 for m in RE_PATTERN_LINE_SPLIT.finditer(pattern):
97 linetext = pattern[last:m.start(0)]
98 if not len(m.group(0)) and not len(text):
99 indent = ''
100 offset = -1
101 col = index - last + 1
102 elif last <= index < m.end(0):
103 indent = '--> '
104 offset = (-1 if index > m.start(0) else 0) + 3
105 col = index - last + 1
106 else:
107 indent = ' '
108 offset = None
109 if len(text):
110 # Regardless of whether we are presented with `\r\n`, `\r`, or `\n`,
111 # we will render the output with just `\n`. We will still log the column
112 # correctly though.
113 text.append('\n')
114 text.append('{}{}'.format(indent, linetext))
115 if offset is not None:
116 text.append('\n')
117 text.append(' ' * (col + offset) + '^')
118 line = current_line
119
120 current_line += 1
121 last = m.end(0)
122
123 return ''.join(text), line, col