File size: 2,303 Bytes
21a9138
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
"""CLI: python -m behaviour {package DIR | diff FILE|- | snippet FILE|-} [--task TEXT | --task-file F]
[--format text|json|both] [--lang js|ts|py|sh] [--out-json PATH]

Static only: analysed code is never executed. Output describes behaviour; it is not a verdict.
"""
import argparse
import json
import sys
from pathlib import Path

from .engine import analyse_diff, analyse_package, analyse_snippet
from .model import KIND_HELP


def _read(src):
    return sys.stdin.read() if src == "-" else Path(src).read_text(encoding="utf-8", errors="replace")


def main(argv=None):
    ap = argparse.ArgumentParser(prog="python -m behaviour", description=__doc__.split("\n\n")[0])
    sub = ap.add_subparsers(dest="mode")
    for name in ("package", "diff", "snippet"):
        p = sub.add_parser(name)
        p.add_argument("input", help="directory" if name == "package" else "file or - for stdin")
        p.add_argument("--task")
        p.add_argument("--task-file")
        p.add_argument("--format", choices=("text", "json", "both"), default="text")
        p.add_argument("--out-json")
        if name == "package":
            p.add_argument("--include-node-modules", action="store_true")
        if name == "snippet":
            p.add_argument("--lang", choices=("js", "ts", "py", "sh", "javascript", "typescript", "python", "shell"))
    sub.add_parser("kinds")
    a = ap.parse_args(argv)
    if a.mode == "kinds":
        for k, v in KIND_HELP.items():
            print(f"{k}: {v}")
        return 0
    if not a.mode:
        ap.print_help()
        return 2
    task = a.task or (Path(a.task_file).read_text(errors="replace") if a.task_file else None)
    if a.mode == "package":
        rep = analyse_package(a.input, task=task, include_node_modules=a.include_node_modules)
    elif a.mode == "diff":
        rep = analyse_diff(_read(a.input), task=task, target=a.input)
    else:
        rep = analyse_snippet(_read(a.input), lang=a.lang, task=task, target="snippet" if a.input == "-" else a.input)
    if a.out_json:
        Path(a.out_json).write_text(json.dumps(rep, indent=1) + "\n")
    if a.format in ("json", "both"):
        print(json.dumps(rep, indent=1))
    if a.format in ("text", "both"):
        print(rep["text"])
    return 0


if __name__ == "__main__":
    sys.exit(main())