Show More
@@ -54,7 +54,7 b' if ispy3:' | |||||
54 | return s.decode(u'latin-1') |
|
54 | return s.decode(u'latin-1') | |
55 |
|
55 | |||
56 | def opentext(f): |
|
56 | def opentext(f): | |
57 |
return open(f, 'r |
|
57 | return open(f, 'r') | |
58 | else: |
|
58 | else: | |
59 | stdin = sys.stdin |
|
59 | stdin = sys.stdin | |
60 | stdout = sys.stdout |
|
60 | stdout = sys.stdout | |
@@ -164,14 +164,14 b' def embedded(basefile, lines, errors, ma' | |||||
164 | ... self.matchfunc = matchfunc |
|
164 | ... self.matchfunc = matchfunc | |
165 | ... def startsat(self, line): |
|
165 | ... def startsat(self, line): | |
166 | ... return self.matchfunc(line) |
|
166 | ... return self.matchfunc(line) | |
167 |
>>> ambig1 = ambigmatcher( |
|
167 | >>> ambig1 = ambigmatcher('ambiguous #1', | |
168 |
... lambda l: l.startswith( |
|
168 | ... lambda l: l.startswith(' $ cat ')) | |
169 |
>>> ambig2 = ambigmatcher( |
|
169 | >>> ambig2 = ambigmatcher('ambiguous #2', | |
170 |
... lambda l: l.endswith( |
|
170 | ... lambda l: l.endswith('<< EOF\\n')) | |
171 |
>>> lines = [ |
|
171 | >>> lines = [' $ cat > foo.py << EOF\\n'] | |
172 | >>> errors = [] |
|
172 | >>> errors = [] | |
173 | >>> matchers = [ambig1, ambig2] |
|
173 | >>> matchers = [ambig1, ambig2] | |
174 |
>>> list(t for t in embedded( |
|
174 | >>> list(t for t in embedded('<dummy>', lines, errors, matchers)) | |
175 | [] |
|
175 | [] | |
176 | >>> b2s(errors) |
|
176 | >>> b2s(errors) | |
177 | ['<dummy>:1: ambiguous line for "ambiguous #1", "ambiguous #2"'] |
|
177 | ['<dummy>:1: ambiguous line for "ambiguous #1", "ambiguous #2"'] | |
@@ -181,21 +181,21 b' def embedded(basefile, lines, errors, ma' | |||||
181 | ctx = filename = code = startline = None # for pyflakes |
|
181 | ctx = filename = code = startline = None # for pyflakes | |
182 |
|
182 | |||
183 | for lineno, line in enumerate(lines, 1): |
|
183 | for lineno, line in enumerate(lines, 1): | |
184 |
if not line.endswith( |
|
184 | if not line.endswith('\n'): | |
185 |
line += |
|
185 | line += '\n' # to normalize EOF line | |
186 | if matcher: # now, inside embedded code |
|
186 | if matcher: # now, inside embedded code | |
187 | if matcher.endsat(ctx, line): |
|
187 | if matcher.endsat(ctx, line): | |
188 | codeatend = matcher.codeatend(ctx, line) |
|
188 | codeatend = matcher.codeatend(ctx, line) | |
189 | if codeatend is not None: |
|
189 | if codeatend is not None: | |
190 | code.append(codeatend) |
|
190 | code.append(codeatend) | |
191 | if not matcher.ignores(ctx): |
|
191 | if not matcher.ignores(ctx): | |
192 |
yield (filename, startline, lineno, |
|
192 | yield (filename, startline, lineno, ''.join(code)) | |
193 | matcher = None |
|
193 | matcher = None | |
194 | # DO NOT "continue", because line might start next fragment |
|
194 | # DO NOT "continue", because line might start next fragment | |
195 | elif not matcher.isinside(ctx, line): |
|
195 | elif not matcher.isinside(ctx, line): | |
196 | # this is an error of basefile |
|
196 | # this is an error of basefile | |
197 | # (if matchers are implemented correctly) |
|
197 | # (if matchers are implemented correctly) | |
198 |
errors.append( |
|
198 | errors.append('%s:%d: unexpected line for "%s"' | |
199 | % (basefile, lineno, matcher.desc)) |
|
199 | % (basefile, lineno, matcher.desc)) | |
200 | # stop extracting embedded code by current 'matcher', |
|
200 | # stop extracting embedded code by current 'matcher', | |
201 | # because appearance of unexpected line might mean |
|
201 | # because appearance of unexpected line might mean | |
@@ -218,9 +218,9 b' def embedded(basefile, lines, errors, ma' | |||||
218 | if matched: |
|
218 | if matched: | |
219 | if len(matched) > 1: |
|
219 | if len(matched) > 1: | |
220 | # this is an error of matchers, maybe |
|
220 | # this is an error of matchers, maybe | |
221 |
errors.append( |
|
221 | errors.append('%s:%d: ambiguous line for %s' % | |
222 | (basefile, lineno, |
|
222 | (basefile, lineno, | |
223 |
|
|
223 | ', '.join(['"%s"' % m.desc | |
224 | for m, c in matched]))) |
|
224 | for m, c in matched]))) | |
225 | # omit extracting embedded code, because choosing |
|
225 | # omit extracting embedded code, because choosing | |
226 | # arbitrary matcher from matched ones might fail to |
|
226 | # arbitrary matcher from matched ones might fail to | |
@@ -239,20 +239,20 b' def embedded(basefile, lines, errors, ma' | |||||
239 | if matcher: |
|
239 | if matcher: | |
240 | # examine whether EOF ends embedded code, because embedded |
|
240 | # examine whether EOF ends embedded code, because embedded | |
241 | # code isn't yet ended explicitly |
|
241 | # code isn't yet ended explicitly | |
242 |
if matcher.endsat(ctx, |
|
242 | if matcher.endsat(ctx, '\n'): | |
243 |
codeatend = matcher.codeatend(ctx, |
|
243 | codeatend = matcher.codeatend(ctx, '\n') | |
244 | if codeatend is not None: |
|
244 | if codeatend is not None: | |
245 | code.append(codeatend) |
|
245 | code.append(codeatend) | |
246 | if not matcher.ignores(ctx): |
|
246 | if not matcher.ignores(ctx): | |
247 |
yield (filename, startline, lineno + 1, |
|
247 | yield (filename, startline, lineno + 1, ''.join(code)) | |
248 | else: |
|
248 | else: | |
249 | # this is an error of basefile |
|
249 | # this is an error of basefile | |
250 | # (if matchers are implemented correctly) |
|
250 | # (if matchers are implemented correctly) | |
251 |
errors.append( |
|
251 | errors.append('%s:%d: unexpected end of file for "%s"' | |
252 | % (basefile, lineno, matcher.desc)) |
|
252 | % (basefile, lineno, matcher.desc)) | |
253 |
|
253 | |||
254 | # heredoc limit mark to ignore embedded code at check-code.py or so |
|
254 | # heredoc limit mark to ignore embedded code at check-code.py or so | |
255 |
heredocignorelimit = |
|
255 | heredocignorelimit = 'NO_CHECK_EOF' | |
256 |
|
256 | |||
257 | # the pattern to match against cases below, and to return a limit mark |
|
257 | # the pattern to match against cases below, and to return a limit mark | |
258 | # string as 'lname' group |
|
258 | # string as 'lname' group | |
@@ -260,47 +260,47 b" heredocignorelimit = b'NO_CHECK_EOF'" | |||||
260 | # - << LIMITMARK |
|
260 | # - << LIMITMARK | |
261 | # - << "LIMITMARK" |
|
261 | # - << "LIMITMARK" | |
262 | # - << 'LIMITMARK' |
|
262 | # - << 'LIMITMARK' | |
263 |
heredoclimitpat = |
|
263 | heredoclimitpat = r'\s*<<\s*(?P<lquote>["\']?)(?P<limit>\w+)(?P=lquote)' | |
264 |
|
264 | |||
265 | class fileheredocmatcher(embeddedmatcher): |
|
265 | class fileheredocmatcher(embeddedmatcher): | |
266 | """Detect "cat > FILE << LIMIT" style embedded code |
|
266 | """Detect "cat > FILE << LIMIT" style embedded code | |
267 |
|
267 | |||
268 | >>> matcher = fileheredocmatcher(b'heredoc .py file', br'[^<]+\\.py') |
|
268 | >>> matcher = fileheredocmatcher(b'heredoc .py file', br'[^<]+\\.py') | |
269 |
>>> b2s(matcher.startsat( |
|
269 | >>> b2s(matcher.startsat(' $ cat > file.py << EOF\\n')) | |
270 | ('file.py', ' > EOF\\n') |
|
270 | ('file.py', ' > EOF\\n') | |
271 |
>>> b2s(matcher.startsat( |
|
271 | >>> b2s(matcher.startsat(' $ cat >>file.py <<EOF\\n')) | |
272 | ('file.py', ' > EOF\\n') |
|
272 | ('file.py', ' > EOF\\n') | |
273 |
>>> b2s(matcher.startsat( |
|
273 | >>> b2s(matcher.startsat(' $ cat> \\x27any file.py\\x27<< "EOF"\\n')) | |
274 | ('any file.py', ' > EOF\\n') |
|
274 | ('any file.py', ' > EOF\\n') | |
275 |
>>> b2s(matcher.startsat( |
|
275 | >>> b2s(matcher.startsat(" $ cat > file.py << 'ANYLIMIT'\\n")) | |
276 | ('file.py', ' > ANYLIMIT\\n') |
|
276 | ('file.py', ' > ANYLIMIT\\n') | |
277 |
>>> b2s(matcher.startsat( |
|
277 | >>> b2s(matcher.startsat(' $ cat<<ANYLIMIT>"file.py"\\n')) | |
278 | ('file.py', ' > ANYLIMIT\\n') |
|
278 | ('file.py', ' > ANYLIMIT\\n') | |
279 |
>>> start = |
|
279 | >>> start = ' $ cat > file.py << EOF\\n' | |
280 | >>> ctx = matcher.startsat(start) |
|
280 | >>> ctx = matcher.startsat(start) | |
281 | >>> matcher.codeatstart(ctx, start) |
|
281 | >>> matcher.codeatstart(ctx, start) | |
282 | >>> b2s(matcher.filename(ctx)) |
|
282 | >>> b2s(matcher.filename(ctx)) | |
283 | 'file.py' |
|
283 | 'file.py' | |
284 | >>> matcher.ignores(ctx) |
|
284 | >>> matcher.ignores(ctx) | |
285 | False |
|
285 | False | |
286 |
>>> inside = |
|
286 | >>> inside = ' > foo = 1\\n' | |
287 | >>> matcher.endsat(ctx, inside) |
|
287 | >>> matcher.endsat(ctx, inside) | |
288 | False |
|
288 | False | |
289 | >>> matcher.isinside(ctx, inside) |
|
289 | >>> matcher.isinside(ctx, inside) | |
290 | True |
|
290 | True | |
291 | >>> b2s(matcher.codeinside(ctx, inside)) |
|
291 | >>> b2s(matcher.codeinside(ctx, inside)) | |
292 | 'foo = 1\\n' |
|
292 | 'foo = 1\\n' | |
293 |
>>> end = |
|
293 | >>> end = ' > EOF\\n' | |
294 | >>> matcher.endsat(ctx, end) |
|
294 | >>> matcher.endsat(ctx, end) | |
295 | True |
|
295 | True | |
296 | >>> matcher.codeatend(ctx, end) |
|
296 | >>> matcher.codeatend(ctx, end) | |
297 |
>>> matcher.endsat(ctx, |
|
297 | >>> matcher.endsat(ctx, ' > EOFEOF\\n') | |
298 | False |
|
298 | False | |
299 |
>>> ctx = matcher.startsat( |
|
299 | >>> ctx = matcher.startsat(' $ cat > file.py << NO_CHECK_EOF\\n') | |
300 | >>> matcher.ignores(ctx) |
|
300 | >>> matcher.ignores(ctx) | |
301 | True |
|
301 | True | |
302 | """ |
|
302 | """ | |
303 |
_prefix = |
|
303 | _prefix = ' > ' | |
304 |
|
304 | |||
305 | def __init__(self, desc, namepat): |
|
305 | def __init__(self, desc, namepat): | |
306 | super(fileheredocmatcher, self).__init__(desc) |
|
306 | super(fileheredocmatcher, self).__init__(desc) | |
@@ -312,13 +312,13 b' class fileheredocmatcher(embeddedmatcher' | |||||
312 | # - > NAMEPAT |
|
312 | # - > NAMEPAT | |
313 | # - > "NAMEPAT" |
|
313 | # - > "NAMEPAT" | |
314 | # - > 'NAMEPAT' |
|
314 | # - > 'NAMEPAT' | |
315 |
namepat = ( |
|
315 | namepat = (r'\s*>>?\s*(?P<nquote>["\']?)(?P<name>%s)(?P=nquote)' | |
316 | % namepat) |
|
316 | % namepat) | |
317 | self._fileres = [ |
|
317 | self._fileres = [ | |
318 | # "cat > NAME << LIMIT" case |
|
318 | # "cat > NAME << LIMIT" case | |
319 |
re.compile( |
|
319 | re.compile(r' \$ \s*cat' + namepat + heredoclimitpat), | |
320 | # "cat << LIMIT > NAME" case |
|
320 | # "cat << LIMIT > NAME" case | |
321 |
re.compile( |
|
321 | re.compile(r' \$ \s*cat' + heredoclimitpat + namepat), | |
322 | ] |
|
322 | ] | |
323 |
|
323 | |||
324 | def startsat(self, line): |
|
324 | def startsat(self, line): | |
@@ -327,7 +327,7 b' class fileheredocmatcher(embeddedmatcher' | |||||
327 | matched = filere.match(line) |
|
327 | matched = filere.match(line) | |
328 | if matched: |
|
328 | if matched: | |
329 | return (matched.group('name'), |
|
329 | return (matched.group('name'), | |
330 |
|
|
330 | ' > %s\n' % matched.group('limit')) | |
331 |
|
331 | |||
332 | def endsat(self, ctx, line): |
|
332 | def endsat(self, ctx, line): | |
333 | return ctx[1] == line |
|
333 | return ctx[1] == line | |
@@ -336,7 +336,7 b' class fileheredocmatcher(embeddedmatcher' | |||||
336 | return line.startswith(self._prefix) |
|
336 | return line.startswith(self._prefix) | |
337 |
|
337 | |||
338 | def ignores(self, ctx): |
|
338 | def ignores(self, ctx): | |
339 |
return |
|
339 | return ' > %s\n' % heredocignorelimit == ctx[1] | |
340 |
|
340 | |||
341 | def filename(self, ctx): |
|
341 | def filename(self, ctx): | |
342 | return ctx[0] |
|
342 | return ctx[0] | |
@@ -357,10 +357,10 b' class pydoctestmatcher(embeddedmatcher):' | |||||
357 | """Detect ">>> code" style embedded python code |
|
357 | """Detect ">>> code" style embedded python code | |
358 |
|
358 | |||
359 | >>> matcher = pydoctestmatcher() |
|
359 | >>> matcher = pydoctestmatcher() | |
360 |
>>> startline = |
|
360 | >>> startline = ' >>> foo = 1\\n' | |
361 | >>> matcher.startsat(startline) |
|
361 | >>> matcher.startsat(startline) | |
362 | True |
|
362 | True | |
363 |
>>> matcher.startsat( |
|
363 | >>> matcher.startsat(' ... foo = 1\\n') | |
364 | False |
|
364 | False | |
365 | >>> ctx = matcher.startsat(startline) |
|
365 | >>> ctx = matcher.startsat(startline) | |
366 | >>> matcher.filename(ctx) |
|
366 | >>> matcher.filename(ctx) | |
@@ -368,45 +368,45 b' class pydoctestmatcher(embeddedmatcher):' | |||||
368 | False |
|
368 | False | |
369 | >>> b2s(matcher.codeatstart(ctx, startline)) |
|
369 | >>> b2s(matcher.codeatstart(ctx, startline)) | |
370 | 'foo = 1\\n' |
|
370 | 'foo = 1\\n' | |
371 |
>>> inside = |
|
371 | >>> inside = ' >>> foo = 1\\n' | |
372 | >>> matcher.endsat(ctx, inside) |
|
372 | >>> matcher.endsat(ctx, inside) | |
373 | False |
|
373 | False | |
374 | >>> matcher.isinside(ctx, inside) |
|
374 | >>> matcher.isinside(ctx, inside) | |
375 | True |
|
375 | True | |
376 | >>> b2s(matcher.codeinside(ctx, inside)) |
|
376 | >>> b2s(matcher.codeinside(ctx, inside)) | |
377 | 'foo = 1\\n' |
|
377 | 'foo = 1\\n' | |
378 |
>>> inside = |
|
378 | >>> inside = ' ... foo = 1\\n' | |
379 | >>> matcher.endsat(ctx, inside) |
|
379 | >>> matcher.endsat(ctx, inside) | |
380 | False |
|
380 | False | |
381 | >>> matcher.isinside(ctx, inside) |
|
381 | >>> matcher.isinside(ctx, inside) | |
382 | True |
|
382 | True | |
383 | >>> b2s(matcher.codeinside(ctx, inside)) |
|
383 | >>> b2s(matcher.codeinside(ctx, inside)) | |
384 | 'foo = 1\\n' |
|
384 | 'foo = 1\\n' | |
385 |
>>> inside = |
|
385 | >>> inside = ' expected output\\n' | |
386 | >>> matcher.endsat(ctx, inside) |
|
386 | >>> matcher.endsat(ctx, inside) | |
387 | False |
|
387 | False | |
388 | >>> matcher.isinside(ctx, inside) |
|
388 | >>> matcher.isinside(ctx, inside) | |
389 | True |
|
389 | True | |
390 | >>> b2s(matcher.codeinside(ctx, inside)) |
|
390 | >>> b2s(matcher.codeinside(ctx, inside)) | |
391 | '\\n' |
|
391 | '\\n' | |
392 |
>>> inside = |
|
392 | >>> inside = ' \\n' | |
393 | >>> matcher.endsat(ctx, inside) |
|
393 | >>> matcher.endsat(ctx, inside) | |
394 | False |
|
394 | False | |
395 | >>> matcher.isinside(ctx, inside) |
|
395 | >>> matcher.isinside(ctx, inside) | |
396 | True |
|
396 | True | |
397 | >>> b2s(matcher.codeinside(ctx, inside)) |
|
397 | >>> b2s(matcher.codeinside(ctx, inside)) | |
398 | '\\n' |
|
398 | '\\n' | |
399 |
>>> end = |
|
399 | >>> end = ' $ foo bar\\n' | |
400 | >>> matcher.endsat(ctx, end) |
|
400 | >>> matcher.endsat(ctx, end) | |
401 | True |
|
401 | True | |
402 | >>> matcher.codeatend(ctx, end) |
|
402 | >>> matcher.codeatend(ctx, end) | |
403 |
>>> end = |
|
403 | >>> end = '\\n' | |
404 | >>> matcher.endsat(ctx, end) |
|
404 | >>> matcher.endsat(ctx, end) | |
405 | True |
|
405 | True | |
406 | >>> matcher.codeatend(ctx, end) |
|
406 | >>> matcher.codeatend(ctx, end) | |
407 | """ |
|
407 | """ | |
408 |
_prefix = |
|
408 | _prefix = ' >>> ' | |
409 |
_prefixre = re.compile( |
|
409 | _prefixre = re.compile(r' (>>>|\.\.\.) ') | |
410 |
|
410 | |||
411 | # If a line matches against not _prefixre but _outputre, that line |
|
411 | # If a line matches against not _prefixre but _outputre, that line | |
412 | # is "an expected output line" (= not a part of code fragment). |
|
412 | # is "an expected output line" (= not a part of code fragment). | |
@@ -416,10 +416,10 b' class pydoctestmatcher(embeddedmatcher):' | |||||
416 | # run-tests.py. But "directive line inside inline python code" |
|
416 | # run-tests.py. But "directive line inside inline python code" | |
417 | # should be rejected by Mercurial reviewers. Therefore, this |
|
417 | # should be rejected by Mercurial reviewers. Therefore, this | |
418 | # regexp does not matche against such directive lines. |
|
418 | # regexp does not matche against such directive lines. | |
419 |
_outputre = re.compile( |
|
419 | _outputre = re.compile(r' $| [^$]') | |
420 |
|
420 | |||
421 | def __init__(self): |
|
421 | def __init__(self): | |
422 |
super(pydoctestmatcher, self).__init__( |
|
422 | super(pydoctestmatcher, self).__init__("doctest style python code") | |
423 |
|
423 | |||
424 | def startsat(self, line): |
|
424 | def startsat(self, line): | |
425 | # ctx is "True" |
|
425 | # ctx is "True" | |
@@ -446,57 +446,57 b' class pydoctestmatcher(embeddedmatcher):' | |||||
446 | def codeinside(self, ctx, line): |
|
446 | def codeinside(self, ctx, line): | |
447 | if self._prefixre.match(line): |
|
447 | if self._prefixre.match(line): | |
448 | return line[len(self._prefix):] # strip prefix ' >>> '/' ... ' |
|
448 | return line[len(self._prefix):] # strip prefix ' >>> '/' ... ' | |
449 |
return |
|
449 | return '\n' # an expected output line is treated as an empty line | |
450 |
|
450 | |||
451 | class pyheredocmatcher(embeddedmatcher): |
|
451 | class pyheredocmatcher(embeddedmatcher): | |
452 | """Detect "python << LIMIT" style embedded python code |
|
452 | """Detect "python << LIMIT" style embedded python code | |
453 |
|
453 | |||
454 | >>> matcher = pyheredocmatcher() |
|
454 | >>> matcher = pyheredocmatcher() | |
455 |
>>> b2s(matcher.startsat( |
|
455 | >>> b2s(matcher.startsat(' $ python << EOF\\n')) | |
456 | ' > EOF\\n' |
|
456 | ' > EOF\\n' | |
457 |
>>> b2s(matcher.startsat( |
|
457 | >>> b2s(matcher.startsat(' $ $PYTHON <<EOF\\n')) | |
458 | ' > EOF\\n' |
|
458 | ' > EOF\\n' | |
459 |
>>> b2s(matcher.startsat( |
|
459 | >>> b2s(matcher.startsat(' $ "$PYTHON"<< "EOF"\\n')) | |
460 | ' > EOF\\n' |
|
460 | ' > EOF\\n' | |
461 |
>>> b2s(matcher.startsat( |
|
461 | >>> b2s(matcher.startsat(" $ $PYTHON << 'ANYLIMIT'\\n")) | |
462 | ' > ANYLIMIT\\n' |
|
462 | ' > ANYLIMIT\\n' | |
463 |
>>> matcher.startsat( |
|
463 | >>> matcher.startsat(' $ "$PYTHON" < EOF\\n') | |
464 |
>>> start = |
|
464 | >>> start = ' $ python << EOF\\n' | |
465 | >>> ctx = matcher.startsat(start) |
|
465 | >>> ctx = matcher.startsat(start) | |
466 | >>> matcher.codeatstart(ctx, start) |
|
466 | >>> matcher.codeatstart(ctx, start) | |
467 | >>> matcher.filename(ctx) |
|
467 | >>> matcher.filename(ctx) | |
468 | >>> matcher.ignores(ctx) |
|
468 | >>> matcher.ignores(ctx) | |
469 | False |
|
469 | False | |
470 |
>>> inside = |
|
470 | >>> inside = ' > foo = 1\\n' | |
471 | >>> matcher.endsat(ctx, inside) |
|
471 | >>> matcher.endsat(ctx, inside) | |
472 | False |
|
472 | False | |
473 | >>> matcher.isinside(ctx, inside) |
|
473 | >>> matcher.isinside(ctx, inside) | |
474 | True |
|
474 | True | |
475 | >>> b2s(matcher.codeinside(ctx, inside)) |
|
475 | >>> b2s(matcher.codeinside(ctx, inside)) | |
476 | 'foo = 1\\n' |
|
476 | 'foo = 1\\n' | |
477 |
>>> end = |
|
477 | >>> end = ' > EOF\\n' | |
478 | >>> matcher.endsat(ctx, end) |
|
478 | >>> matcher.endsat(ctx, end) | |
479 | True |
|
479 | True | |
480 | >>> matcher.codeatend(ctx, end) |
|
480 | >>> matcher.codeatend(ctx, end) | |
481 |
>>> matcher.endsat(ctx, |
|
481 | >>> matcher.endsat(ctx, ' > EOFEOF\\n') | |
482 | False |
|
482 | False | |
483 |
>>> ctx = matcher.startsat( |
|
483 | >>> ctx = matcher.startsat(' $ python << NO_CHECK_EOF\\n') | |
484 | >>> matcher.ignores(ctx) |
|
484 | >>> matcher.ignores(ctx) | |
485 | True |
|
485 | True | |
486 | """ |
|
486 | """ | |
487 |
_prefix = |
|
487 | _prefix = ' > ' | |
488 |
|
488 | |||
489 |
_startre = re.compile( |
|
489 | _startre = re.compile(r' \$ (\$PYTHON|"\$PYTHON"|python).*' + | |
490 | heredoclimitpat) |
|
490 | heredoclimitpat) | |
491 |
|
491 | |||
492 | def __init__(self): |
|
492 | def __init__(self): | |
493 |
super(pyheredocmatcher, self).__init__( |
|
493 | super(pyheredocmatcher, self).__init__("heredoc python invocation") | |
494 |
|
494 | |||
495 | def startsat(self, line): |
|
495 | def startsat(self, line): | |
496 | # ctx is END-LINE-OF-EMBEDDED-CODE |
|
496 | # ctx is END-LINE-OF-EMBEDDED-CODE | |
497 | matched = self._startre.match(line) |
|
497 | matched = self._startre.match(line) | |
498 | if matched: |
|
498 | if matched: | |
499 |
return |
|
499 | return ' > %s\n' % matched.group('limit') | |
500 |
|
500 | |||
501 | def endsat(self, ctx, line): |
|
501 | def endsat(self, ctx, line): | |
502 | return ctx == line |
|
502 | return ctx == line | |
@@ -505,7 +505,7 b' class pyheredocmatcher(embeddedmatcher):' | |||||
505 | return line.startswith(self._prefix) |
|
505 | return line.startswith(self._prefix) | |
506 |
|
506 | |||
507 | def ignores(self, ctx): |
|
507 | def ignores(self, ctx): | |
508 |
return |
|
508 | return ' > %s\n' % heredocignorelimit == ctx | |
509 |
|
509 | |||
510 | def filename(self, ctx): |
|
510 | def filename(self, ctx): | |
511 | return None # no filename |
|
511 | return None # no filename | |
@@ -524,7 +524,7 b' class pyheredocmatcher(embeddedmatcher):' | |||||
524 | pyheredocmatcher(), |
|
524 | pyheredocmatcher(), | |
525 | # use '[^<]+' instead of '\S+', in order to match against |
|
525 | # use '[^<]+' instead of '\S+', in order to match against | |
526 | # paths including whitespaces |
|
526 | # paths including whitespaces | |
527 |
fileheredocmatcher( |
|
527 | fileheredocmatcher('heredoc .py file', r'[^<]+\.py'), | |
528 | ] |
|
528 | ] | |
529 |
|
529 | |||
530 | def pyembedded(basefile, lines, errors): |
|
530 | def pyembedded(basefile, lines, errors): | |
@@ -536,7 +536,7 b' def pyembedded(basefile, lines, errors):' | |||||
536 | _shmatchers = [ |
|
536 | _shmatchers = [ | |
537 | # use '[^<]+' instead of '\S+', in order to match against |
|
537 | # use '[^<]+' instead of '\S+', in order to match against | |
538 | # paths including whitespaces |
|
538 | # paths including whitespaces | |
539 |
fileheredocmatcher( |
|
539 | fileheredocmatcher('heredoc .sh file', r'[^<]+\.sh'), | |
540 | ] |
|
540 | ] | |
541 |
|
541 | |||
542 | def shembedded(basefile, lines, errors): |
|
542 | def shembedded(basefile, lines, errors): | |
@@ -548,8 +548,8 b' def shembedded(basefile, lines, errors):' | |||||
548 | _hgrcmatchers = [ |
|
548 | _hgrcmatchers = [ | |
549 | # use '[^<]+' instead of '\S+', in order to match against |
|
549 | # use '[^<]+' instead of '\S+', in order to match against | |
550 | # paths including whitespaces |
|
550 | # paths including whitespaces | |
551 |
fileheredocmatcher( |
|
551 | fileheredocmatcher('heredoc hgrc file', | |
552 |
|
|
552 | r'(([^/<]+/)+hgrc|\$HGRCPATH|\${HGRCPATH})'), | |
553 | ] |
|
553 | ] | |
554 |
|
554 | |||
555 | def hgrcembedded(basefile, lines, errors): |
|
555 | def hgrcembedded(basefile, lines, errors): | |
@@ -565,14 +565,14 b' if __name__ == "__main__":' | |||||
565 | errors = [] |
|
565 | errors = [] | |
566 | for name, starts, ends, code in embeddedfunc(basefile, lines, errors): |
|
566 | for name, starts, ends, code in embeddedfunc(basefile, lines, errors): | |
567 | if not name: |
|
567 | if not name: | |
568 |
name = |
|
568 | name = '<anonymous>' | |
569 |
writeout( |
|
569 | writeout("%s:%d: %s starts\n" % (basefile, starts, name)) | |
570 | if opts.verbose and code: |
|
570 | if opts.verbose and code: | |
571 |
writeout( |
|
571 | writeout(" |%s\n" % | |
572 |
|
|
572 | "\n |".join(l for l in code.splitlines())) | |
573 |
writeout( |
|
573 | writeout("%s:%d: %s ends\n" % (basefile, ends, name)) | |
574 | for e in errors: |
|
574 | for e in errors: | |
575 |
writeerr( |
|
575 | writeerr("%s\n" % e) | |
576 | return len(errors) |
|
576 | return len(errors) | |
577 |
|
577 | |||
578 | def applyembedded(args, embeddedfunc, opts): |
|
578 | def applyembedded(args, embeddedfunc, opts): | |
@@ -580,11 +580,11 b' if __name__ == "__main__":' | |||||
580 | if args: |
|
580 | if args: | |
581 | for f in args: |
|
581 | for f in args: | |
582 | with opentext(f) as fp: |
|
582 | with opentext(f) as fp: | |
583 |
if showembedded( |
|
583 | if showembedded(f, fp, embeddedfunc, opts): | |
584 | ret = 1 |
|
584 | ret = 1 | |
585 | else: |
|
585 | else: | |
586 | lines = [l for l in stdin.readlines()] |
|
586 | lines = [l for l in stdin.readlines()] | |
587 |
if showembedded( |
|
587 | if showembedded('<stdin>', lines, embeddedfunc, opts): | |
588 | ret = 1 |
|
588 | ret = 1 | |
589 | return ret |
|
589 | return ret | |
590 |
|
590 |
General Comments 0
You need to be logged in to leave comments.
Login now