@@ -101,6 +101,7 @@ def regex_from_encoded_pattern(s):
101101 else : # not an encoded regex
102102 return re .compile (re .escape (s ))
103103
104+
104105# Recipe: dedent (0.1.2)
105106def dedentlines (lines , tabsize = 8 , skip_first_line = False ):
106107 """dedentlines(lines, tabsize=8, skip_first_line=False) -> dedented lines
@@ -116,55 +117,64 @@ def dedentlines(lines, tabsize=8, skip_first_line=False):
116117 """
117118 DEBUG = False
118119 if DEBUG :
119- print ("dedent: dedent(..., tabsize=%d, skip_first_line=%r)" \
120- % (tabsize , skip_first_line ))
120+ print (
121+ "dedent: dedent(..., tabsize=%d, skip_first_line=%r)"
122+ % (tabsize , skip_first_line )
123+ )
121124 margin = None
122125 for i , line in enumerate (lines ):
123- if i == 0 and skip_first_line : continue
126+ if i == 0 and skip_first_line :
127+ continue
124128 indent = 0
125129 for ch in line :
126- if ch == ' ' :
130+ if ch == " " :
127131 indent += 1
128- elif ch == ' \t ' :
132+ elif ch == " \t " :
129133 indent += tabsize - (indent % tabsize )
130- elif ch in ' \r \n ' :
134+ elif ch in " \r \n " :
131135 continue # skip all-whitespace lines
132136 else :
133137 break
134138 else :
135139 continue # skip all-whitespace lines
136- if DEBUG : print ("dedent: indent=%d: %r" % (indent , line ))
140+ if DEBUG :
141+ print ("dedent: indent=%d: %r" % (indent , line ))
137142 if margin is None :
138143 margin = indent
139144 else :
140145 margin = min (margin , indent )
141- if DEBUG : print ("dedent: margin=%r" % margin )
146+ if DEBUG :
147+ print ("dedent: margin=%r" % margin )
142148
143149 if margin is not None and margin > 0 :
144150 for i , line in enumerate (lines ):
145- if i == 0 and skip_first_line : continue
151+ if i == 0 and skip_first_line :
152+ continue
146153 removed = 0
147154 for j , ch in enumerate (line ):
148- if ch == ' ' :
155+ if ch == " " :
149156 removed += 1
150- elif ch == ' \t ' :
157+ elif ch == " \t " :
151158 removed += tabsize - (removed % tabsize )
152- elif ch in '\r \n ' :
153- if DEBUG : print ("dedent: %r: EOL -> strip up to EOL" % line )
159+ elif ch in "\r \n " :
160+ if DEBUG :
161+ print ("dedent: %r: EOL -> strip up to EOL" % line )
154162 lines [i ] = lines [i ][j :]
155163 break
156164 else :
157- raise ValueError ("unexpected non-whitespace char %r in "
158- "line %r while removing %d-space margin"
159- % (ch , line , margin ))
165+ raise ValueError (
166+ "unexpected non-whitespace char %r in "
167+ "line %r while removing %d-space margin" % (ch , line , margin )
168+ )
160169 if DEBUG :
161- print ("dedent: %r: %r -> removed %d/%d" \
162- % (line , ch , removed , margin ))
170+ print (
171+ "dedent: %r: %r -> removed %d/%d" % (line , ch , removed , margin )
172+ )
163173 if removed == margin :
164- lines [i ] = lines [i ][j + 1 :]
174+ lines [i ] = lines [i ][j + 1 :]
165175 break
166176 elif removed > margin :
167- lines [i ] = ' ' * (removed - margin ) + lines [i ][j + 1 :]
177+ lines [i ] = " " * (removed - margin ) + lines [i ][j + 1 :]
168178 break
169179 else :
170180 if removed :
@@ -185,7 +195,7 @@ def dedent(text, tabsize=8, skip_first_line=False):
185195 """
186196 lines = text .splitlines (1 )
187197 dedentlines (lines , tabsize = tabsize , skip_first_line = skip_first_line )
188- return '' .join (lines )
198+ return "" .join (lines )
189199
190200
191201class memoized (object ):
@@ -195,6 +205,7 @@ class memoized(object):
195205
196206 http://wiki.python.org/moin/PythonDecoratorLibrary
197207 """
208+
198209 def __init__ (self , func ):
199210 self .func = func
200211 self .cache = {}
@@ -215,10 +226,10 @@ def __repr__(self):
215226 return self .func .__doc__
216227
217228
218-
219229def xml_oneliner_re_from_tab_width (tab_width ):
220230 """Standalone XML processing instruction regex."""
221- return re .compile (r"""
231+ return re .compile (
232+ r"""
222233 (?:
223234 (?<=\n\n) # Starting after a blank line
224235 | # or
@@ -234,5 +245,36 @@ def xml_oneliner_re_from_tab_width(tab_width):
234245 [ \t]*
235246 (?=\n{2,}|\Z) # followed by a blank line or end of document
236247 )
237- """ % (tab_width - 1 ), re .X )
248+ """
249+ % (tab_width - 1 ),
250+ re .X ,
251+ )
252+
253+
238254xml_oneliner_re_from_tab_width = memoized (xml_oneliner_re_from_tab_width )
255+
256+
257+ def hr_tag_re_from_tab_width (tab_width ):
258+ return re .compile (
259+ r"""
260+ (?:
261+ (?<=\n\n) # Starting after a blank line
262+ | # or
263+ \A\n? # the beginning of the doc
264+ )
265+ ( # save in \1
266+ [ ]{0,%d}
267+ <(hr) # start tag = \2
268+ \b # word break
269+ ([^<>])*? #
270+ /?> # the matching end tag
271+ [ \t]*
272+ (?=\n{2,}|\Z) # followed by a blank line or end of document
273+ )
274+ """
275+ % (tab_width - 1 ),
276+ re .X ,
277+ )
278+
279+
280+ hr_tag_re_from_tab_width = memoized (hr_tag_re_from_tab_width )
0 commit comments