-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathcli.py
More file actions
135 lines (111 loc) · 4 KB
/
cli.py
File metadata and controls
135 lines (111 loc) · 4 KB
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import argparse
import sys
from codemodder import __VERSION__
from codemodder.codemods import DEFAULT_CODEMODS
from codemodder.logging import logger
class ArgumentParser(argparse.ArgumentParser):
def error(self, message):
"""If there is an argument parsing error, print the `--help` message,
log the error, and exit with status code `3`."""
self.print_help(sys.stderr)
logger.error("CLI error: %s", message)
sys.exit(3)
class ListAction(argparse.Action):
""" """
def _print_codemods(self):
for codemod in DEFAULT_CODEMODS:
print(f"pixee:python/{codemod.full_name()}")
def __call__(self, parser, *args, **kwargs):
"""
Print codemod(s) metadata in the following format:
pixee:python/secure-random
pixee:python/url-sandbox
...
and exit gracefully.
"""
self._print_codemods()
parser.exit()
class CsvListAction(argparse.Action):
"""
argparse Action to convert "a,b,c" into ["a", "b", "c"]
"""
def __call__(self, parser, namespace, values, option_string=None):
items = set(values.split(","))
self.validate_items(items)
setattr(namespace, self.dest, items)
def validate_items(self, items):
"""Basic Action does not validate the items"""
class ValidatedCodmods(CsvListAction):
"""
argparse Action to convert "codemod1,codemod2,codemod3" into a list
representation and validate against existing codemods
"""
def validate_items(self, items):
codemod_names = [codemod.METADATA.NAME for codemod in DEFAULT_CODEMODS]
unrecognized_codemods = [name for name in items if name not in codemod_names]
if unrecognized_codemods:
args = {
"values": unrecognized_codemods,
"choices": ", ".join(map(repr, codemod_names)),
}
msg = "invalid choice(s): %(values)r (choose from %(choices)s)"
raise argparse.ArgumentError(self, msg % args)
def parse_args(argv):
"""
Parse CLI arguments according to:
https://www.notion.so/pixee/Codemodder-CLI-Arguments
"""
parser = ArgumentParser(description="Run codemods and change code.")
parser.add_argument("directory", type=str, help="path to find files")
parser.add_argument(
"--output",
type=str,
help="name of output file to produce",
default="stdout",
required=True,
)
codemod_args_group = parser.add_mutually_exclusive_group()
codemod_args_group.add_argument(
"--codemod-exclude",
action=ValidatedCodmods,
help="Comma-separated set of codemod ID(s) to exclude",
)
codemod_args_group.add_argument(
"--codemod-include",
action=ValidatedCodmods,
help="Comma-separated set of codemod ID(s) to include",
)
parser.add_argument("--version", action="version", version=__VERSION__)
parser.add_argument(
"--list", action=ListAction, nargs=0, help="Print codemod(s) metadata"
)
parser.add_argument(
"--output-format",
type=str,
help="the format for the data output file",
default="codetf",
choices=["codetf", "diff"],
)
parser.add_argument(
"--dry-run",
action=argparse.BooleanOptionalAction,
help="do everything except make changes to files",
)
parser.add_argument("--verbose", type=bool, help="print more to stdout")
parser.add_argument(
"--path-exclude",
action=CsvListAction,
help="Comma-separated set of UNIX glob patterns to exclude",
)
parser.add_argument(
"--path-include",
action=CsvListAction,
help="Comma-separated set of UNIX glob patterns to include",
)
# At this time we don't do anything with the sarif arg.
parser.add_argument(
"--sarif",
action=CsvListAction,
help="Comma-separated set of path(s) to SARIF file(s) to feed to the codemods",
)
return parser.parse_args(argv)