Show More
@@ -40,6 +40,8 b' try:' | |||||
40 | except ImportError: |
|
40 | except ImportError: | |
41 | re2 = None |
|
41 | re2 = None | |
42 |
|
42 | |||
|
43 | import testparseutil | |||
|
44 | ||||
43 | def compilere(pat, multiline=False): |
|
45 | def compilere(pat, multiline=False): | |
44 | if multiline: |
|
46 | if multiline: | |
45 | pat = '(?m)' + pat |
|
47 | pat = '(?m)' + pat | |
@@ -402,6 +404,15 b' pypats = [' | |||||
402 | ] + commonpypats[1] |
|
404 | ] + commonpypats[1] | |
403 | ] |
|
405 | ] | |
404 |
|
406 | |||
|
407 | # patterns to check *.py for embedded ones in test script | |||
|
408 | embeddedpypats = [ | |||
|
409 | [ | |||
|
410 | ] + commonpypats[0], | |||
|
411 | # warnings | |||
|
412 | [ | |||
|
413 | ] + commonpypats[1] | |||
|
414 | ] | |||
|
415 | ||||
405 | # common filters to convert *.py |
|
416 | # common filters to convert *.py | |
406 | commonpyfilters = [ |
|
417 | commonpyfilters = [ | |
407 | (r"""(?msx)(?P<comment>\#.*?$)| |
|
418 | (r"""(?msx)(?P<comment>\#.*?$)| | |
@@ -426,6 +437,10 b' pynfpats = [' | |||||
426 | [], |
|
437 | [], | |
427 | ] |
|
438 | ] | |
428 |
|
439 | |||
|
440 | # filters to convert *.py for embedded ones in test script | |||
|
441 | embeddedpyfilters = [ | |||
|
442 | ] + commonpyfilters | |||
|
443 | ||||
429 | # extension non-filter patterns |
|
444 | # extension non-filter patterns | |
430 | pyextnfpats = [ |
|
445 | pyextnfpats = [ | |
431 | [(r'^"""\n?[A-Z]', "don't capitalize docstring title")], |
|
446 | [(r'^"""\n?[A-Z]', "don't capitalize docstring title")], | |
@@ -560,6 +575,15 b' checks = [' | |||||
560 | allfilesfilters, allfilespats), |
|
575 | allfilesfilters, allfilespats), | |
561 | ] |
|
576 | ] | |
562 |
|
577 | |||
|
578 | # (desc, | |||
|
579 | # func to pick up embedded code fragments, | |||
|
580 | # list of patterns to convert target files | |||
|
581 | # list of patterns to detect errors/warnings) | |||
|
582 | embeddedchecks = [ | |||
|
583 | ('embedded python', | |||
|
584 | testparseutil.pyembedded, embeddedpyfilters, embeddedpypats) | |||
|
585 | ] | |||
|
586 | ||||
563 | def _preparepats(): |
|
587 | def _preparepats(): | |
564 | def preparefailandwarn(failandwarn): |
|
588 | def preparefailandwarn(failandwarn): | |
565 | for pats in failandwarn: |
|
589 | for pats in failandwarn: | |
@@ -580,7 +604,7 b' def _preparepats():' | |||||
580 | for i, flt in enumerate(filters): |
|
604 | for i, flt in enumerate(filters): | |
581 | filters[i] = re.compile(flt[0]), flt[1] |
|
605 | filters[i] = re.compile(flt[0]), flt[1] | |
582 |
|
606 | |||
583 | for cs in (checks,): |
|
607 | for cs in (checks, embeddedchecks): | |
584 | for c in cs: |
|
608 | for c in cs: | |
585 | failandwarn = c[-1] |
|
609 | failandwarn = c[-1] | |
586 | preparefailandwarn(failandwarn) |
|
610 | preparefailandwarn(failandwarn) | |
@@ -674,6 +698,30 b' def checkfile(f, logfunc=_defaultlogger.' | |||||
674 | if fc: |
|
698 | if fc: | |
675 | result = False |
|
699 | result = False | |
676 |
|
700 | |||
|
701 | if f.endswith('.t') and "no-" "check-code" not in pre: | |||
|
702 | if debug: | |||
|
703 | print("Checking embedded code in %s" % (f)) | |||
|
704 | ||||
|
705 | prelines = pre.splitlines() | |||
|
706 | embeddederros = [] | |||
|
707 | for name, embedded, filters, pats in embeddedchecks: | |||
|
708 | # "reset curmax at each repetition" treats maxerr as "max | |||
|
709 | # nubmer of errors in an actual file per entry of | |||
|
710 | # (embedded)checks" | |||
|
711 | curmaxerr = maxerr | |||
|
712 | ||||
|
713 | for found in embedded(f, prelines, embeddederros): | |||
|
714 | filename, starts, ends, code = found | |||
|
715 | fc = _checkfiledata(name, f, code, filters, pats, context, | |||
|
716 | logfunc, curmaxerr, warnings, blame, debug, | |||
|
717 | lineno, offset=starts - 1) | |||
|
718 | if fc: | |||
|
719 | result = False | |||
|
720 | if curmaxerr: | |||
|
721 | if fc >= curmaxerr: | |||
|
722 | break | |||
|
723 | curmaxerr -= fc | |||
|
724 | ||||
677 | return result |
|
725 | return result | |
678 |
|
726 | |||
679 | def _checkfiledata(name, f, filedata, filters, pats, context, |
|
727 | def _checkfiledata(name, f, filedata, filters, pats, context, |
@@ -379,3 +379,51 b' should break rules depending on result o' | |||||
379 | > class empty(object): |
|
379 | > class empty(object): | |
380 | omit superfluous pass |
|
380 | omit superfluous pass | |
381 | [1] |
|
381 | [1] | |
|
382 | ||||
|
383 | Check code fragments embedded in test script | |||
|
384 | ||||
|
385 | $ cat > embedded-code.t <<NO_CHECK_EOF | |||
|
386 | > code fragment in doctest style | |||
|
387 | > >>> x = (1,2) | |||
|
388 | > ... | |||
|
389 | > ... x = (1,2) | |||
|
390 | > | |||
|
391 | > code fragment in heredoc style | |||
|
392 | > $ python <<EOF | |||
|
393 | > > x = (1,2) | |||
|
394 | > > EOF | |||
|
395 | > | |||
|
396 | > code fragment in file heredoc style | |||
|
397 | > $ python > file.py <<EOF | |||
|
398 | > > x = (1,2) | |||
|
399 | > > EOF | |||
|
400 | > NO_CHECK_EOF | |||
|
401 | $ "$check_code" embedded-code.t | |||
|
402 | embedded-code.t:2: | |||
|
403 | > x = (1,2) | |||
|
404 | missing whitespace after , | |||
|
405 | embedded-code.t:4: | |||
|
406 | > x = (1,2) | |||
|
407 | missing whitespace after , | |||
|
408 | embedded-code.t:8: | |||
|
409 | > x = (1,2) | |||
|
410 | missing whitespace after , | |||
|
411 | embedded-code.t:13: | |||
|
412 | > x = (1,2) | |||
|
413 | missing whitespace after , | |||
|
414 | [1] | |||
|
415 | ||||
|
416 | "max warnings per file" is shared by all embedded code fragments | |||
|
417 | ||||
|
418 | $ "$check_code" --per-file=3 embedded-code.t | |||
|
419 | embedded-code.t:2: | |||
|
420 | > x = (1,2) | |||
|
421 | missing whitespace after , | |||
|
422 | embedded-code.t:4: | |||
|
423 | > x = (1,2) | |||
|
424 | missing whitespace after , | |||
|
425 | embedded-code.t:8: | |||
|
426 | > x = (1,2) | |||
|
427 | missing whitespace after , | |||
|
428 | (too many errors, giving up) | |||
|
429 | [1] |
General Comments 0
You need to be logged in to leave comments.
Login now