pyntcli 0.1.85__py3-none-any.whl → 0.1.86__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyntcli/__init__.py +1 -1
- pyntcli/commands/burp.py +3 -1
- pyntcli/commands/command.py +6 -5
- pyntcli/commands/har.py +7 -5
- pyntcli/commands/listen.py +8 -7
- pyntcli/commands/newman.py +2 -1
- pyntcli/commands/postman.py +2 -2
- pyntcli/commands/root.py +8 -1
- pyntcli/main.py +15 -9
- pyntcli/pynt_docker/pynt_container.py +8 -1
- pyntcli/ui/pynt_errors.py +17 -5
- pyntcli/ui/ui_thread.py +50 -32
- {pyntcli-0.1.85.dist-info → pyntcli-0.1.86.dist-info}/METADATA +1 -1
- {pyntcli-0.1.85.dist-info → pyntcli-0.1.86.dist-info}/RECORD +17 -17
- {pyntcli-0.1.85.dist-info → pyntcli-0.1.86.dist-info}/WHEEL +0 -0
- {pyntcli-0.1.85.dist-info → pyntcli-0.1.86.dist-info}/entry_points.txt +0 -0
- {pyntcli-0.1.85.dist-info → pyntcli-0.1.86.dist-info}/top_level.txt +0 -0
pyntcli/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.1.
|
|
1
|
+
__version__ = "0.1.86"
|
pyntcli/commands/burp.py
CHANGED
|
@@ -261,6 +261,7 @@ class BurpCommand(sub_command.PyntSubCommand):
|
|
|
261
261
|
)
|
|
262
262
|
return
|
|
263
263
|
|
|
264
|
+
ui_thread.print_verbose("Parsing burp xml")
|
|
264
265
|
doc = parse_xml(args.xml)
|
|
265
266
|
if not doc:
|
|
266
267
|
ui_thread.print(
|
|
@@ -290,8 +291,9 @@ class BurpCommand(sub_command.PyntSubCommand):
|
|
|
290
291
|
ui_thread.print_generator(proxy_docker.stdout)
|
|
291
292
|
|
|
292
293
|
util.wait_for_healthcheck("http://localhost:{}".format(args.port))
|
|
294
|
+
ui_thread.print_verbose(util.GOT_INITIAL_HEALTHCHECK_MESSAGE)
|
|
293
295
|
ui_thread.print(ui_thread.PrinterText(
|
|
294
|
-
|
|
296
|
+
"Pynt docker is ready",
|
|
295
297
|
ui_thread.PrinterText.INFO,
|
|
296
298
|
))
|
|
297
299
|
|
pyntcli/commands/command.py
CHANGED
|
@@ -161,8 +161,9 @@ class CommandSubCommand(sub_command.PyntSubCommand):
|
|
|
161
161
|
ui_thread.print_generator(proxy_docker.stdout)
|
|
162
162
|
|
|
163
163
|
util.wait_for_healthcheck("http://localhost:{}".format(args.port))
|
|
164
|
+
ui_thread.print_verbose(util.GOT_INITIAL_HEALTHCHECK_MESSAGE)
|
|
164
165
|
ui_thread.print(ui_thread.PrinterText(
|
|
165
|
-
|
|
166
|
+
"Pynt docker is ready",
|
|
166
167
|
ui_thread.PrinterText.INFO,
|
|
167
168
|
))
|
|
168
169
|
|
|
@@ -199,10 +200,10 @@ class CommandSubCommand(sub_command.PyntSubCommand):
|
|
|
199
200
|
self._stop_proxy(args)
|
|
200
201
|
|
|
201
202
|
with ui_thread.progress(
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
203
|
+
"ws://localhost:{}/progress?scanId={}".format(args.port, self.scan_id),
|
|
204
|
+
partial(lambda *args: None),
|
|
205
|
+
"scan in progress...",
|
|
206
|
+
100,
|
|
206
207
|
):
|
|
207
208
|
html_report = self._get_report(args, "html")
|
|
208
209
|
html_report_path = os.path.join(
|
pyntcli/commands/har.py
CHANGED
|
@@ -51,6 +51,7 @@ class HarSubCommand(sub_command.PyntSubCommand):
|
|
|
51
51
|
return har_cmd
|
|
52
52
|
|
|
53
53
|
def run_cmd(self, args: argparse.Namespace):
|
|
54
|
+
ui_thread.print_verbose("Building container")
|
|
54
55
|
port = util.find_open_port()
|
|
55
56
|
container = pynt_container.get_container_with_arguments(
|
|
56
57
|
args, pynt_container.PyntDockerPort(src=str(port), dest=port, name="--port")
|
|
@@ -94,18 +95,19 @@ class HarSubCommand(sub_command.PyntSubCommand):
|
|
|
94
95
|
)
|
|
95
96
|
|
|
96
97
|
healthcheck()
|
|
98
|
+
ui_thread.print_verbose(util.GOT_INITIAL_HEALTHCHECK_MESSAGE)
|
|
97
99
|
ui_thread.print(ui_thread.PrinterText(
|
|
98
|
-
|
|
100
|
+
"Pynt docker is ready",
|
|
99
101
|
ui_thread.PrinterText.INFO,
|
|
100
102
|
))
|
|
101
103
|
|
|
102
104
|
ui_thread.print_generator(ui_thread.AnsiText.wrap_gen(har_docker.stdout))
|
|
103
105
|
|
|
104
106
|
with ui_thread.progress(
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
"ws://localhost:{}/progress".format(port),
|
|
108
|
+
healthcheck,
|
|
109
|
+
"scan in progress...",
|
|
110
|
+
100,
|
|
109
111
|
):
|
|
110
112
|
while har_docker.is_alive():
|
|
111
113
|
time.sleep(1)
|
pyntcli/commands/listen.py
CHANGED
|
@@ -57,7 +57,7 @@ class ListenSubCommand(sub_command.PyntSubCommand):
|
|
|
57
57
|
listen_cmd.add_argument("--allow-errors", action="store_true")
|
|
58
58
|
listen_cmd.add_argument("--ca-path", type=str, default="")
|
|
59
59
|
listen_cmd.add_argument("--report", type=str, default="")
|
|
60
|
-
listen_cmd.add_argument("--return-error", choices=["all-findings", "errors-only", "never"], default="never"
|
|
60
|
+
listen_cmd.add_argument("--return-error", choices=["all-findings", "errors-only", "never"], default="never")
|
|
61
61
|
listen_cmd.print_usage = self.print_usage
|
|
62
62
|
listen_cmd.print_help = self.print_usage
|
|
63
63
|
return listen_cmd
|
|
@@ -140,8 +140,9 @@ class ListenSubCommand(sub_command.PyntSubCommand):
|
|
|
140
140
|
ui_thread.print_generator(proxy_docker.stdout)
|
|
141
141
|
|
|
142
142
|
util.wait_for_healthcheck("http://localhost:{}".format(args.port))
|
|
143
|
+
ui_thread.print_verbose(util.GOT_INITIAL_HEALTHCHECK_MESSAGE)
|
|
143
144
|
ui_thread.print(ui_thread.PrinterText(
|
|
144
|
-
|
|
145
|
+
"Pynt docker is ready",
|
|
145
146
|
ui_thread.PrinterText.INFO,
|
|
146
147
|
))
|
|
147
148
|
|
|
@@ -170,9 +171,9 @@ class ListenSubCommand(sub_command.PyntSubCommand):
|
|
|
170
171
|
self._stop_proxy(args)
|
|
171
172
|
|
|
172
173
|
with ui_thread.progress(
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
174
|
+
"ws://localhost:{}/progress?scanId={}".format(args.port, self.scan_id),
|
|
175
|
+
partial(lambda *args: None),
|
|
176
|
+
"scan in progress...", 100):
|
|
176
177
|
html_report = self._get_report(args, "html")
|
|
177
178
|
html_report_path = os.path.join(
|
|
178
179
|
tempfile.gettempdir(), "pynt_report_{}.html".format(int(time.time()))
|
|
@@ -189,12 +190,12 @@ class ListenSubCommand(sub_command.PyntSubCommand):
|
|
|
189
190
|
json_report_path = util.get_user_report_path(full_path, "json")
|
|
190
191
|
|
|
191
192
|
if html_report:
|
|
192
|
-
with open(html_report_path, "w",encoding="utf-8") as html_file:
|
|
193
|
+
with open(html_report_path, "w", encoding="utf-8") as html_file:
|
|
193
194
|
html_file.write(html_report)
|
|
194
195
|
webbrowser.open("file://{}".format(html_report_path))
|
|
195
196
|
|
|
196
197
|
if json_report:
|
|
197
|
-
with open(json_report_path, "w",encoding="utf-8") as json_file:
|
|
198
|
+
with open(json_report_path, "w", encoding="utf-8") as json_file:
|
|
198
199
|
json_file.write(json_report)
|
|
199
200
|
reporter = cli_reporter.PyntReporter(json_report_path)
|
|
200
201
|
reporter.print_summary()
|
pyntcli/commands/newman.py
CHANGED
|
@@ -116,8 +116,9 @@ class NewmanSubCommand(sub_command.PyntSubCommand):
|
|
|
116
116
|
)
|
|
117
117
|
|
|
118
118
|
healthcheck()
|
|
119
|
+
ui_thread.print_verbose(util.GOT_INITIAL_HEALTHCHECK_MESSAGE)
|
|
119
120
|
ui_thread.print(ui_thread.PrinterText(
|
|
120
|
-
|
|
121
|
+
"Pynt docker is ready",
|
|
121
122
|
ui_thread.PrinterText.INFO,
|
|
122
123
|
))
|
|
123
124
|
|
pyntcli/commands/postman.py
CHANGED
|
@@ -94,7 +94,6 @@ class PostmanSubCommand(sub_command.PyntSubCommand):
|
|
|
94
94
|
|
|
95
95
|
container = pynt_container.get_container_with_arguments(args, pynt_container.PyntDockerPort("5001", args.port, name="--port"))
|
|
96
96
|
|
|
97
|
-
|
|
98
97
|
postman_docker = pynt_container.PyntContainer(image_name=pynt_container.PYNT_DOCKER_IMAGE,
|
|
99
98
|
tag="postman-latest",
|
|
100
99
|
detach=True,
|
|
@@ -104,8 +103,9 @@ class PostmanSubCommand(sub_command.PyntSubCommand):
|
|
|
104
103
|
ui_thread.print_generator(postman_docker.stdout)
|
|
105
104
|
|
|
106
105
|
util.wait_for_healthcheck("http://localhost:{}".format(args.port))
|
|
106
|
+
ui_thread.print_verbose(util.GOT_INITIAL_HEALTHCHECK_MESSAGE)
|
|
107
107
|
ui_thread.print(ui_thread.PrinterText(
|
|
108
|
-
|
|
108
|
+
"Pynt docker is ready",
|
|
109
109
|
ui_thread.PrinterText.INFO,
|
|
110
110
|
))
|
|
111
111
|
|
pyntcli/commands/root.py
CHANGED
|
@@ -22,7 +22,7 @@ def root_usage():
|
|
|
22
22
|
.with_line("\tpynt-id - view your pynt-id to use when running pynt in CI pipeline")
|
|
23
23
|
.with_line("\tlogout - log out from your user")
|
|
24
24
|
.with_line("")
|
|
25
|
-
.with_line("Run pynt [COMMAND] -h to get help on a specific command", style=ui_thread.PrinterText.INFO,)
|
|
25
|
+
.with_line("Run pynt [COMMAND] -h to get help on a specific command", style=ui_thread.PrinterText.INFO, )
|
|
26
26
|
)
|
|
27
27
|
|
|
28
28
|
|
|
@@ -68,6 +68,13 @@ class BaseCommand:
|
|
|
68
68
|
parser.add_argument("--transport-config", type=str, default="")
|
|
69
69
|
parser.add_argument("--application-id", type=str, default="", required=False)
|
|
70
70
|
parser.add_argument("--proxy", type=str, default="", required=False)
|
|
71
|
+
parser.add_argument(
|
|
72
|
+
"--verbose",
|
|
73
|
+
default=False,
|
|
74
|
+
required=False,
|
|
75
|
+
action="store_true",
|
|
76
|
+
help="use to get more detailed execution information",
|
|
77
|
+
)
|
|
71
78
|
|
|
72
79
|
def get_subparser(self) -> argparse._SubParsersAction:
|
|
73
80
|
if self.subparser is None:
|
pyntcli/main.py
CHANGED
|
@@ -33,18 +33,17 @@ def signal_handler(signal_number, frame):
|
|
|
33
33
|
exit(0)
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
def
|
|
36
|
+
def assert_docker_availability():
|
|
37
37
|
pynt_container.get_docker_type()
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
def print_header():
|
|
41
41
|
ui_thread.print(ui_thread.PrinterText(*ui_thread.pynt_header())
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
.with_line(*ui_thread.pynt_version())
|
|
43
|
+
.with_line(""))
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
def start_analytics():
|
|
47
|
-
user_id = login.user_id()
|
|
46
|
+
def start_analytics(user_id: str):
|
|
48
47
|
if user_id:
|
|
49
48
|
analytics.set_user_id(user_id)
|
|
50
49
|
log.add_user_details(user_id)
|
|
@@ -72,9 +71,14 @@ def main():
|
|
|
72
71
|
if argv[1] == "logout":
|
|
73
72
|
logout()
|
|
74
73
|
return
|
|
74
|
+
if [n for n in argv if "--verbose" in n]:
|
|
75
|
+
ui_thread.VERBOSE = True
|
|
75
76
|
log.set_source(__version__)
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
ui_thread.print_verbose("Logging in...")
|
|
78
|
+
user_id = login.user_id()
|
|
79
|
+
start_analytics(user_id)
|
|
80
|
+
ui_thread.print_verbose("Asserting docker is properly installed")
|
|
81
|
+
assert_docker_availability()
|
|
78
82
|
signal.signal(signal.SIGINT, signal_handler)
|
|
79
83
|
cli = pynt_cmd.PyntCommand()
|
|
80
84
|
cli.run_cmd(cli.parse_args(argv[1:]))
|
|
@@ -85,7 +89,8 @@ def main():
|
|
|
85
89
|
ui_thread.print(ui_thread.PrinterText("Docker was unavailable, please make sure docker is installed and running.", ui_thread.PrinterText.WARNING))
|
|
86
90
|
analytics.emit(analytics.ERROR, {"error": "docker unavailable. e: {}".format(e)})
|
|
87
91
|
except SSLError as e:
|
|
88
|
-
ui_thread.print(
|
|
92
|
+
ui_thread.print(
|
|
93
|
+
ui_thread.PrinterText("We encountered SSL issues and could not proceed, this may be the cause of a VPN or a Firewall in place. Run again with --insecure", ui_thread.PrinterText.WARNING))
|
|
89
94
|
analytics.emit(analytics.ERROR, {"error": "ssl error. e: {}".format(e)})
|
|
90
95
|
except login.Timeout as e:
|
|
91
96
|
ui_thread.print(ui_thread.PrinterText("Pynt CLI exited due to incomplete registration, please try again.", ui_thread.PrinterText.WARNING))
|
|
@@ -117,7 +122,8 @@ def main():
|
|
|
117
122
|
exit(1)
|
|
118
123
|
except Exception as e:
|
|
119
124
|
analytics.emit(analytics.ERROR, {"error": "{}".format(e)})
|
|
120
|
-
pynt_errors.unexpected_error()
|
|
125
|
+
pynt_errors.unexpected_error(e)
|
|
126
|
+
|
|
121
127
|
finally:
|
|
122
128
|
log.flush_logger()
|
|
123
129
|
shutdown_cli()
|
|
@@ -106,6 +106,9 @@ def get_container_with_arguments(args: argparse.Namespace, *port_args: PyntDocke
|
|
|
106
106
|
docker_arguments += ["--transport-config", tc_name]
|
|
107
107
|
mounts.append(create_mount(os.path.abspath(args.transport_config), "/etc/pynt/{}".format(tc_name)))
|
|
108
108
|
|
|
109
|
+
if "verbose" in args and args.verbose:
|
|
110
|
+
docker_arguments.append("--verbose")
|
|
111
|
+
|
|
109
112
|
env = {PYNT_ID: CredStore().get_tokens(), "PYNT_SAAS_URL": PYNT_SAAS}
|
|
110
113
|
if user_set_all_variables():
|
|
111
114
|
add_env_variables(env)
|
|
@@ -184,7 +187,8 @@ class PyntContainer():
|
|
|
184
187
|
return self.docker_client.images.pull(self.image, tag=self.tag)
|
|
185
188
|
except APIError as e:
|
|
186
189
|
analytics.emit(analytics.ERROR, {"error": "Unable to pull image from ghcr: {}".format(e)})
|
|
187
|
-
ui_thread.print(ui_thread.PrinterText("Error: Docker unable to pull latest Pynt image due to VPN/proxy. If using a mirror for Docker images, visit docs.pynt.io for help.",
|
|
190
|
+
ui_thread.print(ui_thread.PrinterText("Error: Docker unable to pull latest Pynt image due to VPN/proxy. If using a mirror for Docker images, visit docs.pynt.io for help.",
|
|
191
|
+
ui_thread.PrinterText.WARNING))
|
|
188
192
|
return None
|
|
189
193
|
|
|
190
194
|
def get_image(self):
|
|
@@ -202,6 +206,8 @@ class PyntContainer():
|
|
|
202
206
|
self._create_docker_client()
|
|
203
207
|
|
|
204
208
|
self.running = True
|
|
209
|
+
|
|
210
|
+
ui_thread.print_verbose("Killing other pynt containers if such exist")
|
|
205
211
|
self.kill_other_instances()
|
|
206
212
|
|
|
207
213
|
ui_thread.print(ui_thread.PrinterText("Pulling latest docker", ui_thread.PrinterText.INFO))
|
|
@@ -222,6 +228,7 @@ class PyntContainer():
|
|
|
222
228
|
|
|
223
229
|
run_arguments.update(self.base_container.docker_type.get_argumets())
|
|
224
230
|
|
|
231
|
+
ui_thread.print_verbose("Running pynt docker with arguments:\n {}".format(" ".join(args)))
|
|
225
232
|
c = self.docker_client.containers.run(**run_arguments)
|
|
226
233
|
self.container_name = c.name
|
|
227
234
|
self.stdout = c.logs(stream=True)
|
pyntcli/ui/pynt_errors.py
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
from pyntcli.ui import ui_thread
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
|
|
4
|
+
def unexpected_error(original):
|
|
5
|
+
printer_text = ui_thread.PrinterText("An Unexpected Error Occurred", style=ui_thread.PrinterText.WARNING) \
|
|
6
|
+
.with_line("")
|
|
7
|
+
|
|
8
|
+
if ui_thread.VERBOSE:
|
|
9
|
+
msg = str(original) or repr(original)
|
|
10
|
+
if msg:
|
|
11
|
+
printer_text.with_line(f"e: {msg}")
|
|
12
|
+
|
|
13
|
+
printer_text = printer_text.with_line(
|
|
14
|
+
"Please tell us about it in our community channel and we will help you figure it out:",
|
|
15
|
+
style=ui_thread.PrinterText.HEADER) \
|
|
16
|
+
.with_line("https://join.slack.com/t/pynt-community/shared_invite/zt-1mvacojz5-WNjbH4HN8iksmKpCLTxOiQ",
|
|
17
|
+
style=ui_thread.PrinterText.HEADER)
|
|
18
|
+
|
|
19
|
+
ui_thread.print(printer_text)
|
pyntcli/ui/ui_thread.py
CHANGED
|
@@ -12,13 +12,16 @@ from typing import Tuple
|
|
|
12
12
|
from pyntcli import __version__ as cli_version
|
|
13
13
|
from pyntcli.ui.progress import PyntProgress
|
|
14
14
|
|
|
15
|
+
VERBOSE = False
|
|
16
|
+
|
|
17
|
+
|
|
15
18
|
class PrinterText():
|
|
16
19
|
DEFAULT = 0
|
|
17
20
|
HEADER = 1
|
|
18
21
|
INFO = 2
|
|
19
22
|
WARNING = 3
|
|
20
23
|
|
|
21
|
-
def __init__(self,text,style=DEFAULT):
|
|
24
|
+
def __init__(self, text, style=DEFAULT):
|
|
22
25
|
self.text = Text(text, PrinterText.get_style(style))
|
|
23
26
|
|
|
24
27
|
@staticmethod
|
|
@@ -37,57 +40,67 @@ class PrinterText():
|
|
|
37
40
|
self.text.append(Text(line, PrinterText.get_style(style)))
|
|
38
41
|
return self
|
|
39
42
|
|
|
43
|
+
|
|
40
44
|
class AnsiText():
|
|
41
45
|
def __init__(self, data) -> None:
|
|
42
46
|
self.data = data
|
|
43
|
-
|
|
47
|
+
|
|
44
48
|
@staticmethod
|
|
45
49
|
def wrap_gen(gen):
|
|
46
50
|
for v in gen:
|
|
47
51
|
yield AnsiText(v)
|
|
48
52
|
|
|
53
|
+
|
|
49
54
|
class Spinner():
|
|
50
55
|
def __init__(self, prompt, style) -> None:
|
|
51
56
|
self.prompt = prompt
|
|
52
|
-
self.style = style
|
|
57
|
+
self.style = style
|
|
53
58
|
self.runnning = False
|
|
54
|
-
|
|
59
|
+
|
|
55
60
|
def __enter__(self):
|
|
56
|
-
return self
|
|
61
|
+
return self
|
|
57
62
|
|
|
58
63
|
def __exit__(self, exc_type, exc_value, exc_traceback):
|
|
59
64
|
self.running = False
|
|
60
65
|
|
|
61
|
-
def pynt_version()-> Tuple[str,int]:
|
|
62
|
-
return "Pynt CLI version " + cli_version,PrinterText.DEFAULT
|
|
63
66
|
|
|
64
|
-
def
|
|
65
|
-
return "
|
|
67
|
+
def pynt_version() -> Tuple[str, int]:
|
|
68
|
+
return "Pynt CLI version " + cli_version, PrinterText.DEFAULT
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def pynt_header() -> Tuple[str, int]:
|
|
72
|
+
return "API Security testing autopilot", PrinterText.DEFAULT
|
|
73
|
+
|
|
66
74
|
|
|
67
75
|
def gen_func_loop(gen):
|
|
68
76
|
for l in gen:
|
|
69
77
|
data = l
|
|
70
|
-
if type(data) == bytes:
|
|
78
|
+
if type(data) == bytes:
|
|
71
79
|
data = l.decode("utf-8")
|
|
72
80
|
if not isinstance(data, AnsiText) and data[-1] == "\n":
|
|
73
81
|
data = data[:-1]
|
|
74
82
|
_print(data)
|
|
75
|
-
|
|
83
|
+
|
|
84
|
+
|
|
76
85
|
def print_generator(gen):
|
|
77
|
-
t = Thread(target=gen_func_loop, args=(gen,), daemon=True)
|
|
86
|
+
t = Thread(target=gen_func_loop, args=(gen,), daemon=True)
|
|
78
87
|
t.start()
|
|
79
88
|
|
|
80
|
-
|
|
89
|
+
|
|
90
|
+
def _print(s):
|
|
81
91
|
Printer.instance().print(s)
|
|
82
92
|
|
|
83
|
-
|
|
84
|
-
|
|
93
|
+
|
|
94
|
+
def print(s):
|
|
95
|
+
if type(s) == bytes:
|
|
85
96
|
s = s.decode("utf-8")
|
|
86
97
|
_print(s)
|
|
87
98
|
|
|
99
|
+
|
|
88
100
|
def stop():
|
|
89
101
|
Printer.instance().stop()
|
|
90
102
|
|
|
103
|
+
|
|
91
104
|
class Printer():
|
|
92
105
|
_instace = None
|
|
93
106
|
|
|
@@ -96,31 +109,31 @@ class Printer():
|
|
|
96
109
|
self.run_thread = Thread(target=self._print_in_loop, daemon=True)
|
|
97
110
|
self.print_queue = queue.Queue()
|
|
98
111
|
self.console = Console(tab_size=4)
|
|
99
|
-
|
|
100
|
-
@staticmethod
|
|
112
|
+
|
|
113
|
+
@staticmethod
|
|
101
114
|
def instance():
|
|
102
115
|
if not Printer._instace:
|
|
103
|
-
Printer._instace = Printer()
|
|
104
|
-
Printer._instace.start()
|
|
116
|
+
Printer._instace = Printer()
|
|
117
|
+
Printer._instace.start()
|
|
105
118
|
|
|
106
119
|
return Printer._instace
|
|
107
120
|
|
|
108
121
|
def start(self):
|
|
109
122
|
self.running = True
|
|
110
123
|
self.run_thread.start()
|
|
111
|
-
|
|
124
|
+
|
|
112
125
|
def _handle_spinner(self, spinner):
|
|
113
|
-
spinner.running = True
|
|
126
|
+
spinner.running = True
|
|
114
127
|
s = Status(spinner.prompt, spinner=spinner.style, console=self.console)
|
|
115
128
|
s.start()
|
|
116
129
|
while spinner.running and self.running:
|
|
117
130
|
time.sleep(0.5)
|
|
118
131
|
s.stop()
|
|
119
|
-
|
|
132
|
+
|
|
120
133
|
def _handle_progress(self, progress):
|
|
121
134
|
if not progress.trackable:
|
|
122
135
|
return
|
|
123
|
-
progress.running = True
|
|
136
|
+
progress.running = True
|
|
124
137
|
with Progress(console=self.console, transient=True) as p:
|
|
125
138
|
t = p.add_task(description=progress.description, total=progress.total)
|
|
126
139
|
for update in progress.trackable:
|
|
@@ -131,9 +144,9 @@ class Printer():
|
|
|
131
144
|
|
|
132
145
|
def _print_in_loop(self):
|
|
133
146
|
while self.running:
|
|
134
|
-
try:
|
|
147
|
+
try:
|
|
135
148
|
data = self.print_queue.get(timeout=1)
|
|
136
|
-
if isinstance(data, list):
|
|
149
|
+
if isinstance(data, list):
|
|
137
150
|
data = data[0]
|
|
138
151
|
if isinstance(data, Spinner):
|
|
139
152
|
self._handle_spinner(data)
|
|
@@ -148,29 +161,34 @@ class Printer():
|
|
|
148
161
|
self.console.print(data)
|
|
149
162
|
except queue.Empty:
|
|
150
163
|
pass
|
|
151
|
-
|
|
164
|
+
|
|
152
165
|
while not self.print_queue.empty():
|
|
153
166
|
self.console.print(self.print_queue.get())
|
|
154
167
|
|
|
155
|
-
|
|
156
168
|
def print(self, data):
|
|
157
|
-
if isinstance(data,PrinterText):
|
|
169
|
+
if isinstance(data, PrinterText):
|
|
158
170
|
data = data.text
|
|
159
171
|
if isinstance(data, AnsiText):
|
|
160
172
|
data = Text.from_ansi(data.data.decode())
|
|
161
173
|
self.print_queue.put(data)
|
|
162
|
-
|
|
174
|
+
|
|
163
175
|
def stop(self):
|
|
164
176
|
self.running = False
|
|
165
177
|
self.run_thread.join()
|
|
166
178
|
|
|
167
|
-
|
|
179
|
+
|
|
180
|
+
def spinner(prompt, style):
|
|
168
181
|
s = Spinner(prompt, style)
|
|
169
182
|
_print([s])
|
|
170
183
|
return s
|
|
171
184
|
|
|
172
|
-
|
|
173
|
-
|
|
185
|
+
|
|
186
|
+
def progress(what_to_track, healthcheck, description, total=100):
|
|
187
|
+
pointer_to_progress = [PyntProgress(what_to_track, healthcheck, total, description)]
|
|
174
188
|
_print(pointer_to_progress)
|
|
175
189
|
return pointer_to_progress[0]
|
|
176
190
|
|
|
191
|
+
|
|
192
|
+
def print_verbose(text: str):
|
|
193
|
+
if VERBOSE:
|
|
194
|
+
print(PrinterText(text, PrinterText.INFO))
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
pyntcli/__init__.py,sha256=
|
|
2
|
-
pyntcli/main.py,sha256=
|
|
1
|
+
pyntcli/__init__.py,sha256=daW0dTSMLeXJ53ouWqpbphS98YVWhR0zyXXnZpqK-Ps,23
|
|
2
|
+
pyntcli/main.py,sha256=eJFpT-haLVQAYP71_ZHjNaA5iG2wvDXy8km84GU0Mwo,6009
|
|
3
3
|
pyntcli/analytics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
pyntcli/analytics/send.py,sha256=pJOyOWl3g_Vm9apKK3LzNVqsnC6zsWA1bCK3ZegbLpc,3637
|
|
5
5
|
pyntcli/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
pyntcli/auth/login.py,sha256=TljsRXbEkNI1YUrKm5mlTw4YiecYScYUsit8Z8vstss,5228
|
|
7
7
|
pyntcli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
pyntcli/commands/burp.py,sha256=
|
|
9
|
-
pyntcli/commands/command.py,sha256=
|
|
10
|
-
pyntcli/commands/har.py,sha256
|
|
8
|
+
pyntcli/commands/burp.py,sha256=tDGWzgHKfMnKot1jI7JghvHk29VMZsnfcyNuRZTO2Lk,11753
|
|
9
|
+
pyntcli/commands/command.py,sha256=076tUOnqHBSogoGt8h2fnyZWeGWO5eEfHIECbefdS1s,9715
|
|
10
|
+
pyntcli/commands/har.py,sha256=-RxuX_lw7JAY46oxHlp5N9Twm5Sc3VLVbHpWEwtuGFg,3976
|
|
11
11
|
pyntcli/commands/id_command.py,sha256=UBEgMIpm4vauTCsKyixltiGUolNg_OfHEJvJ_i5BpJY,943
|
|
12
|
-
pyntcli/commands/listen.py,sha256=
|
|
13
|
-
pyntcli/commands/newman.py,sha256=
|
|
14
|
-
pyntcli/commands/postman.py,sha256=
|
|
12
|
+
pyntcli/commands/listen.py,sha256=Mm5TY5e896-NhDOImRUB3N8gaaXtcZdCSdV92NLt8eM,8702
|
|
13
|
+
pyntcli/commands/newman.py,sha256=qvrVLL3BqiugdNPTi-KBI-BXXDYMSRMu4BPEs6Dfz_U,5094
|
|
14
|
+
pyntcli/commands/postman.py,sha256=CgX4KTF8qR008LiIsiSrNLyXdgPre3CwVz3AENnOcB8,4924
|
|
15
15
|
pyntcli/commands/pynt_cmd.py,sha256=KOl9guUtesO2JcMM5nPKKkjnK6F9HV4jHHcoUk4KVhw,2825
|
|
16
|
-
pyntcli/commands/root.py,sha256=
|
|
16
|
+
pyntcli/commands/root.py,sha256=inffMhaMJykoRC0T2f7uF3f5BEdJw_c6Q1e2FTG4bfU,3511
|
|
17
17
|
pyntcli/commands/static_file_extensions.py,sha256=PZJb02BI-64tbU-j3rdCNsXzTh7gkIDGxGKbKNw3h5k,1995
|
|
18
18
|
pyntcli/commands/sub_command.py,sha256=GF3-rE_qk2L4jGPFqHLm9SdGINmu3EakhjJTFyWjRms,374
|
|
19
19
|
pyntcli/commands/util.py,sha256=spTI_3z-fd0q7o1htvl-mw9-yKbO2ZESDAL-AsgWCb0,3217
|
|
@@ -21,7 +21,7 @@ pyntcli/log/__init__.py,sha256=cOGwOYzMoshEbZiiasBGkj6wF0SBu3Jdpl-AuakDesw,19
|
|
|
21
21
|
pyntcli/log/log.py,sha256=cWCdWmUaAwePwdhYDcgNMEG9d9RM34sGahxBCYEdv2Y,1069
|
|
22
22
|
pyntcli/pynt_docker/__init__.py,sha256=PQIOVxc7XXtMLfEX7ojgwf_Z3mmTllO3ZvzUZTPOxQY,30
|
|
23
23
|
pyntcli/pynt_docker/container_utils.py,sha256=_Onn7loInzyJAG2-Uk6CGpsuRyelmUFHOvtJj4Uzi9A,175
|
|
24
|
-
pyntcli/pynt_docker/pynt_container.py,sha256=
|
|
24
|
+
pyntcli/pynt_docker/pynt_container.py,sha256=c3gwOpPvDRWofHqv1p-jsQ24TQOlBFdFqYbwFMiJ0Rs,9079
|
|
25
25
|
pyntcli/store/__init__.py,sha256=xuS9OB21F6B1sUx5XPGxz_6WpG6-KTMbuq50RrZS5OY,29
|
|
26
26
|
pyntcli/store/json_connector.py,sha256=UGs3uORw3iyn0YJ8kzab-veEZToA6d-ByXYuqEleWsA,560
|
|
27
27
|
pyntcli/store/store.py,sha256=9KwalOd1EA1VtYwr9oJgBsPgUYakX5uyif_sNXGQ614,1917
|
|
@@ -30,14 +30,14 @@ pyntcli/transport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
|
|
|
30
30
|
pyntcli/transport/pynt_requests.py,sha256=KiEG3hNcwY7DLIJDCq-7LIPq54yYQcDBhHe3KhpqRTc,1563
|
|
31
31
|
pyntcli/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
32
32
|
pyntcli/ui/progress.py,sha256=RrnO_jJNunoyupylakmWmHOEPw3lh99OHpKBzL6OBiE,1008
|
|
33
|
-
pyntcli/ui/pynt_errors.py,sha256=
|
|
33
|
+
pyntcli/ui/pynt_errors.py,sha256=Pwxf2eIkXbQg060vnaMm4ivthbohDalxVDK6-Kag2iU,727
|
|
34
34
|
pyntcli/ui/report.py,sha256=W-icPSZrGLOubXgam0LpOvHLl_aZg9Zx9qIkL8Ym5PE,1930
|
|
35
|
-
pyntcli/ui/ui_thread.py,sha256=
|
|
35
|
+
pyntcli/ui/ui_thread.py,sha256=4YzpO5dDrWpbTovMdHvv9ZQdLFJamZEAKXjF9rIIIoQ,5039
|
|
36
36
|
tests/conftest.py,sha256=gToq5K74GtgeGQXjFvXSzMaE6axBYxAzcFG5XJPOXjI,427
|
|
37
37
|
tests/auth/test_login.py,sha256=KFlzWhXBAuwdi7GXf16gCB3ya94LQG2wjcSChE149rQ,3798
|
|
38
38
|
tests/store/test_cred_store.py,sha256=_7-917EtNC9eKEumO2_lt-7KuDmCwOZFaowCm7DbA_A,254
|
|
39
|
-
pyntcli-0.1.
|
|
40
|
-
pyntcli-0.1.
|
|
41
|
-
pyntcli-0.1.
|
|
42
|
-
pyntcli-0.1.
|
|
43
|
-
pyntcli-0.1.
|
|
39
|
+
pyntcli-0.1.86.dist-info/METADATA,sha256=7vQ3Epe9eMRgT06mRKDpiwrzSNi-qsa1lwubvzouPDM,463
|
|
40
|
+
pyntcli-0.1.86.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
41
|
+
pyntcli-0.1.86.dist-info/entry_points.txt,sha256=kcGmqAxXDttNk2EPRcqunc_LTVp61gzakz0v-GEE2SY,43
|
|
42
|
+
pyntcli-0.1.86.dist-info/top_level.txt,sha256=u9MDStwVHB7UG8PUcODeWCul_NvzL2EzoLvSlgwLHFs,30
|
|
43
|
+
pyntcli-0.1.86.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|