##// END OF EJS Templates
import-checker: parse python code from .t files
timeless -
r28922:4ec62a08 default
parent child Browse files
Show More
@@ -5,6 +5,7 b' from __future__ import absolute_import, '
5 5 import ast
6 6 import collections
7 7 import os
8 import re
8 9 import sys
9 10
10 11 # Import a minimal set of stdlib modules needed for list_stdlib_modules()
@@ -568,10 +569,97 b' def find_cycles(imports):'
568 569 def _cycle_sortkey(c):
569 570 return len(c), c
570 571
572 def embedded(f, modname, src):
573 """Extract embedded python code
574
575 >>> def test(fn, lines):
576 ... for s, m, f, l in embedded(fn, "example", lines):
577 ... print("%s %s %s" % (m, f, l))
578 ... print(repr(s))
579 >>> lines = [
580 ... 'comment',
581 ... ' >>> from __future__ import print_function',
582 ... " >>> ' multiline",
583 ... " ... string'",
584 ... ' ',
585 ... 'comment',
586 ... ' $ cat > foo.py <<EOF',
587 ... ' > from __future__ import print_function',
588 ... ' > EOF',
589 ... ]
590 >>> test("example.t", lines)
591 example[2] doctest.py 2
592 "from __future__ import print_function\\n' multiline\\nstring'\\n"
593 example[7] foo.py 7
594 'from __future__ import print_function\\n'
595 """
596 inlinepython = 0
597 shpython = 0
598 script = []
599 prefix = 6
600 t = ''
601 n = 0
602 for l in src:
603 n += 1
604 if not l.endswith(b'\n'):
605 l += b'\n'
606 if l.startswith(b' >>> '): # python inlines
607 if shpython:
608 print("%s:%d: Parse Error" % (f, n))
609 if not inlinepython:
610 # We've just entered a Python block.
611 inlinepython = n
612 t = 'doctest.py'
613 script.append(l[prefix:])
614 continue
615 if l.startswith(b' ... '): # python inlines
616 script.append(l[prefix:])
617 continue
618 cat = re.search(r"\$ \s*cat\s*>\s*(\S+\.py)\s*<<\s*EOF", l)
619 if cat:
620 if inlinepython:
621 yield ''.join(script), ("%s[%d]" %
622 (modname, inlinepython)), t, inlinepython
623 script = []
624 inlinepython = 0
625 shpython = n
626 t = cat.group(1)
627 continue
628 if shpython and l.startswith(b' > '): # sh continuation
629 if l == b' > EOF\n':
630 yield ''.join(script), ("%s[%d]" %
631 (modname, shpython)), t, shpython
632 script = []
633 shpython = 0
634 else:
635 script.append(l[4:])
636 continue
637 if inlinepython and l == b' \n':
638 yield ''.join(script), ("%s[%d]" %
639 (modname, inlinepython)), t, inlinepython
640 script = []
641 inlinepython = 0
642 continue
643
571 644 def sources(f, modname):
645 """Yields possibly multiple sources from a filepath
646
647 input: filepath, modulename
648 yields: script(string), modulename, filepath, linenumber
649
650 For embedded scripts, the modulename and filepath will be different
651 from the function arguments. linenumber is an offset relative to
652 the input file.
653 """
654 py = False
572 655 if f.endswith('.py'):
573 656 with open(f) as src:
574 yield src.read(), modname
657 yield src.read(), modname, f, 0
658 py = True
659 if py or f.endswith('.t'):
660 with open(f) as src:
661 for script, modname, t, line in embedded(f, modname, src):
662 yield script, modname, t, line
575 663
576 664 def main(argv):
577 665 if len(argv) < 2 or (argv[1] == '-' and len(argv) > 2):
@@ -587,18 +675,18 b' def main(argv):'
587 675 modname = dotted_name_of_path(source_path, trimpure=True)
588 676 localmods[modname] = source_path
589 677 for localmodname, source_path in sorted(localmods.items()):
590 for src, modname in sources(source_path, localmodname):
678 for src, modname, name, line in sources(source_path, localmodname):
591 679 try:
592 680 used_imports[modname] = sorted(
593 imported_modules(src, modname, source_path, localmods,
681 imported_modules(src, modname, name, localmods,
594 682 ignore_nested=True))
595 683 for error, lineno in verify_import_convention(modname, src,
596 684 localmods):
597 685 any_errors = True
598 print('%s:%d: %s' % (source_path, lineno, error))
686 print('%s:%d: %s' % (source_path, lineno + line, error))
599 687 except SyntaxError as e:
600 688 print('%s:%d: SyntaxError: %s' %
601 (source_path, e.lineno, e))
689 (source_path, e.lineno + line, e))
602 690 cycles = find_cycles(used_imports)
603 691 if cycles:
604 692 firstmods = set()
General Comments 0
You need to be logged in to leave comments. Login now