pyntcli 0.1.115__py3-none-any.whl → 0.1.117__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 CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.115"
1
+ __version__ = "0.1.117"
pyntcli/auth/login.py CHANGED
@@ -31,13 +31,6 @@ PYNT_SAAS = os.environ.get("PYNT_SAAS_URL") if os.environ.get(
31
31
  "PYNT_SAAS_URL") else "https://api.pynt.io/v1"
32
32
  PYNT_APP_URL = os.environ.get("PYNT_APP_URL") if os.environ.get(
33
33
  "PYNT_APP_URL") else "https://app.pynt.io"
34
- PYNT_BUCKET_NAME = os.environ.get(
35
- "PYNT_BUCKET_NAME") if os.environ.get("PYNT_BUCKET_NAME") else ""
36
- PYNT_PARAM1 = os.environ.get(
37
- "PYNT_PARAM1") if os.environ.get("PYNT_PARAM1") else ""
38
- PYNT_PARAM2 = os.environ.get(
39
- "PYNT_PARAM2") if os.environ.get("PYNT_PARAM2") else ""
40
-
41
34
 
42
35
  def generate_device_code() -> str:
43
36
  """
@@ -7,8 +7,9 @@ from pyntcli.analytics import send as analytics
7
7
  from pyntcli.transport import pynt_requests
8
8
  from pyntcli.ui import ui_thread
9
9
  from pyntcli.ui import prompt
10
- from pyntcli.store import CredStore, StateStore
10
+ from pyntcli.store import StateStore
11
11
  import pyntcli.log.log as log
12
+ from pyntcli.saas_client.saas_client import pynt_client
12
13
 
13
14
  from requests.exceptions import SSLError, HTTPError
14
15
 
@@ -123,27 +124,26 @@ class PyntCommand:
123
124
  Returns:
124
125
  bool: True if it's a business-plan user
125
126
  """
126
- saas_url = "https://api.pynt.io/v1/config"
127
- headers = {}
128
- with CredStore() as store:
129
- access_keys = store.get_access_token()
130
- token_type = store.get_token_type()
131
- headers["Authorization"] = f"{token_type} {access_keys}"
132
127
  try:
133
- response = requests.get(saas_url, headers=headers, timeout=10)
134
128
 
135
- if response.status_code == requests.codes.ok:
129
+ if pynt_client.get_config():
136
130
  return True
137
- else:
138
- return False
139
- except requests.exceptions.RequestException as e:
140
- # Catch all other request exceptions
141
- logger.debug(f"An error occurred when accessing '{saas_url}': {e}")
131
+
132
+ return False
133
+ except HTTPError as e:
142
134
  return False
143
135
 
144
136
  def _post_login_args_validation(self, args: argparse.Namespace, command: str, is_business_plan_user: bool):
145
137
  if getattr(args, "application_name"):
146
- if getattr(args, "yes") or self._is_auto_create_app_confirmed(args.application_name):
138
+ try:
139
+ pynt_client.get_application_by_name(args.application_name)
140
+ except HTTPError as e:
141
+ if e.response.status_code == 404:
142
+ if getattr(args, "yes") or self._is_auto_create_app_confirmed(args.application_name):
143
+ return
144
+ else:
145
+ raise UserAbortedException()
146
+ if getattr(args, "yes") or self._is_missing_app_id_confirmed():
147
147
  return
148
148
  else:
149
149
  raise UserAbortedException()
@@ -180,7 +180,7 @@ class PyntCommand:
180
180
  return True
181
181
 
182
182
  if prompt.confirmation_prompt_with_timeout(confirmation_message, default=default_confirmation, timeout=15):
183
- prompts_history["missing_app_id"] = {"last_confirmation": current_time.strftime("%Y-%m-%d %H:%M:%S")}
183
+ prompts_history[prompt_history_key] = {"last_confirmation": current_time.strftime("%Y-%m-%d %H:%M:%S")}
184
184
  state_store.put_prompts_history(
185
185
  prompts_history)
186
186
  return True
@@ -195,5 +195,5 @@ class PyntCommand:
195
195
 
196
196
 
197
197
  def _is_auto_create_app_confirmed(self, application_name: str) -> bool:
198
- return self.is_confirmed("auto_create_application", f"Application {application_name} will be created automatically if it does not exist.\n" +
199
- f"Do you want to continue without the application name {application_name}?", "yes")
198
+ return self.is_confirmed("", f"Application {application_name} will be created automatically if it does not exist.\n" +
199
+ f"Do you want to continue with the application name {application_name}?", "yes")
@@ -1,7 +1,53 @@
1
-
2
1
  import socket
2
+ import subprocess
3
+ import time
4
+ from typing import Optional, List
5
+
6
+ GRACEFUL_KILL_TIMEOUT_SECONDS = 10
3
7
 
4
8
 
5
9
  def is_port_in_use(port: int) -> bool:
6
10
  with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
7
- return s.connect_ex(('localhost', port)) == 0
11
+ return s.connect_ex(("localhost", port)) == 0
12
+
13
+
14
+ def list_running_containers(
15
+ name: Optional[str] = None, container_id: Optional[str] = None
16
+ ) -> List[str]:
17
+ ps_filter = []
18
+ if name is not None:
19
+ ps_filter.extend(["-f", f"name={name}"])
20
+ elif container_id is not None:
21
+ ps_filter.extend(["-f", f"id={container_id}"])
22
+
23
+ output = subprocess.check_output(
24
+ ["docker", "ps", "-a", "-q", *ps_filter],
25
+ text=True,
26
+ )
27
+ return output.splitlines()
28
+
29
+
30
+ def kill_container_gracefully(container_id: str):
31
+ subprocess.run(
32
+ ["docker", "kill", "--signal", "SIGINT", container_id],
33
+ stdout=subprocess.DEVNULL,
34
+ stderr=subprocess.DEVNULL,
35
+ )
36
+
37
+ for _ in range(GRACEFUL_KILL_TIMEOUT_SECONDS):
38
+ time.sleep(1)
39
+ is_still_running = len(list_running_containers(container_id=container_id)) > 0
40
+ if not is_still_running:
41
+ return
42
+
43
+ if len(list_running_containers(container_id=container_id)) > 0:
44
+ kill_container_gracefully(container_id)
45
+
46
+
47
+ def kill_container(container_id: str):
48
+ # `doccker remove -f` sends SIGKILL
49
+ subprocess.run(
50
+ ["docker", "remove", "-f", container_id],
51
+ stdout=subprocess.DEVNULL,
52
+ stderr=subprocess.DEVNULL,
53
+ )
@@ -5,18 +5,17 @@ import os
5
5
  import json
6
6
  import argparse
7
7
  import threading
8
+ from datetime import datetime
8
9
  from typing import List
9
- import base64
10
10
 
11
11
  from . import container_utils
12
12
 
13
13
  from pyntcli.ui import ui_thread
14
14
  from pyntcli.analytics import send as analytics
15
15
  from pyntcli.store import CredStore
16
- from pyntcli.auth.login import PYNT_ID, PYNT_SAAS, PYNT_BUCKET_NAME, PYNT_PARAM1, PYNT_PARAM2
16
+ from pyntcli.auth.login import PYNT_ID, PYNT_SAAS
17
17
 
18
18
  PYNT_DOCKER_IMAGE = "ghcr.io/pynt-io/pynt"
19
- IMAGE_TAGS = ["postman-latest", "newman-latest", "har-latest", "proxy-latest", "v1-latest"]
20
19
 
21
20
 
22
21
  def create_mount(src, destination, mount_type="bind"):
@@ -94,8 +93,9 @@ class DockerContainerConfig:
94
93
  self.docker_arguments = build_docker_args(integration_name, args, port_args)
95
94
  self.mounts = get_docker_mounts(args)
96
95
  self.env_vars = {PYNT_ID: CredStore().get_tokens(), "PYNT_SAAS_URL": PYNT_SAAS}
97
- if user_set_all_variables():
98
- add_env_variables(self.env_vars)
96
+ otel_endpoint = os.environ.get("OTEL_COLLECTOR_ENDPOINT")
97
+ if otel_endpoint:
98
+ self.env_vars["OTEL_COLLECTOR_ENDPOINT"] = otel_endpoint
99
99
 
100
100
 
101
101
  def get_image_config(args: argparse.Namespace) -> PyntDockerImage:
@@ -121,16 +121,6 @@ def is_network_host() -> bool:
121
121
  return True
122
122
 
123
123
 
124
- def user_set_all_variables():
125
- return all([PYNT_BUCKET_NAME, PYNT_PARAM1, PYNT_PARAM2])
126
-
127
-
128
- def add_env_variables(env: dict):
129
- env["PYNT_BUCKET_NAME"] = PYNT_BUCKET_NAME
130
- env["PYNT_PARAM1"] = base64.b64encode(PYNT_PARAM1.encode('utf-8')).decode('utf-8')
131
- env["PYNT_PARAM2"] = base64.b64encode(PYNT_PARAM2.encode('utf-8')).decode('utf-8')
132
-
133
-
134
124
  def value_from_environment_variable(key):
135
125
  e = os.environ.get(key)
136
126
 
@@ -193,6 +183,35 @@ def get_docker_mounts(args: argparse.Namespace) -> list:
193
183
  return mounts
194
184
 
195
185
 
186
+ class DockerLogFollower(threading.Thread):
187
+ def __init__(self, docker_exec: str, container_id: str):
188
+ super().__init__(target=self._run, name="docker logs follower")
189
+ self.docker_exec = docker_exec
190
+ self.container_id = container_id
191
+
192
+ def _run(self):
193
+ logs_process = subprocess.Popen(
194
+ [self.docker_exec, "logs", "-f", self.container_id],
195
+ stdout=subprocess.PIPE,
196
+ stderr=subprocess.STDOUT,
197
+ text=True,
198
+ )
199
+
200
+ while True:
201
+ line = logs_process.stdout.readline()
202
+ if not line:
203
+ break
204
+
205
+ now = datetime.now().astimezone().strftime("%Y-%m-%d %H:%M:%S %z")
206
+ log_line = ui_thread.Text(f"{now} [container]", "default on grey53")
207
+ log_line.append(f" {line}", "bold yellow on default")
208
+
209
+ ui_thread.print(log_line)
210
+
211
+
212
+
213
+ logs_process.wait()
214
+
196
215
  class PyntContainerNative:
197
216
  def __init__(self, container_config: DockerContainerConfig):
198
217
  self.config = container_config
@@ -255,61 +274,38 @@ class PyntContainerNative:
255
274
  process = subprocess.Popen(docker_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
256
275
  stdout, stderr = process.communicate()
257
276
 
258
- if stderr:
259
- print(stderr)
260
-
261
277
  container_id = stdout.strip()
262
278
 
263
279
  if process.returncode and process.returncode != 0:
264
- ui_thread.print_verbose(f"Unable to perform docker run command, return code: {process.returncode}")
265
- raise DockerNativeUnavailableException(f"Unable to perform docker run command, return code: {process.returncode}")
280
+ formatted_response = f"Unable to perform docker run command, return code: {process.returncode}"
281
+ if ui_thread.VERBOSE:
282
+ if stderr is not None and len(stderr) > 0:
283
+ formatted_response += f"\nstderr\n---\n\n{stderr}"
284
+ if stdout is not None and len(stdout) > 0:
285
+ formatted_response += f"\nstdout\n---\n\n{stdout}"
286
+ raise DockerNativeUnavailableException(formatted_response)
266
287
 
267
- # Start log streaming in a separate thread
268
288
  if ui_thread.VERBOSE:
269
- log_thread = threading.Thread(target=self.stream_docker_logs, args=(container_id,))
270
- log_thread.daemon = True
271
- log_thread.start()
272
-
273
- def stream_docker_logs(self, container_id):
274
- logs_process = subprocess.Popen(
275
- ['docker', 'logs', '-f', container_id],
276
- stdout=subprocess.PIPE,
277
- stderr=subprocess.PIPE,
278
- text=True
279
- )
280
-
281
- while True:
282
- log_output = logs_process.stdout.readline()
283
- if log_output == '' and logs_process.poll() is not None:
284
- break
285
- if log_output:
286
- print(log_output.strip())
289
+ # Start log streaming in a separate thread
290
+ DockerLogFollower(docker_exec, container_id).start()
287
291
 
288
- logs_process.stdout.close()
289
-
290
- def kill_other_instances(self, report_to_user=True):
292
+ def kill_other_instances(self, gracefully: bool) -> int:
291
293
  ui_thread.print_verbose("Killing other pynt containers if such exist")
294
+ killed_containers = 0
292
295
  try:
293
- for _ in IMAGE_TAGS:
294
- command = ["docker", "ps", "-a", "-q", "-f", f"name={self.container_name}"]
295
- containers_output = subprocess.check_output(command, text=True)
296
- if not containers_output:
297
- continue
298
-
299
- container_ids = containers_output.splitlines()
300
- for container_id in container_ids:
301
- kill_command = ["docker", "kill", container_id]
302
- remove_command = ["docker", "remove", container_id]
303
- subprocess.run(kill_command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
304
- subprocess.run(remove_command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
305
- if report_to_user:
306
- ui_thread.print(
307
- ui_thread.PrinterText("Another Pynt container was running, killed it", ui_thread.PrinterText))
308
-
296
+ container_ids = container_utils.list_running_containers(name=self.container_name)
297
+ for container_id in container_ids:
298
+ if gracefully:
299
+ container_utils.kill_container_gracefully(container_id)
300
+ else:
301
+ container_utils.kill_container(container_id)
302
+ killed_containers += 1
309
303
  except subprocess.CalledProcessError:
310
304
  analytics.emit(analytics.ERROR, {"error": "Unable to kill other pynt containers"})
311
305
  ui_thread.print(ui_thread.PrinterText("Error: Unable to kill other pynt containers", ui_thread.PrinterText.WARNING))
312
306
 
307
+ return killed_containers
308
+
313
309
  def fetch_and_validate_image(self):
314
310
  try:
315
311
  ui_thread.print(ui_thread.PrinterText("Pulling latest docker image", ui_thread.PrinterText.INFO))
@@ -343,11 +339,18 @@ class PyntContainerNative:
343
339
  def stop(self):
344
340
  if not self.running:
345
341
  return
346
- self.kill_other_instances(report_to_user=False)
342
+ self.kill_other_instances(gracefully=True)
347
343
  self.running = False
348
344
 
349
345
  def pre_run_validation(self, port):
350
- self.kill_other_instances()
346
+ killed_containers = self.kill_other_instances(gracefully=False)
347
+ if killed_containers > 0:
348
+ ui_thread.print(
349
+ ui_thread.PrinterText(
350
+ "Another Pynt container was running, killed it",
351
+ ui_thread.PrinterText,
352
+ )
353
+ )
351
354
 
352
355
  ui_thread.print_verbose("Checking if port is in use")
353
356
  if container_utils.is_port_in_use(int(port)):
@@ -0,0 +1 @@
1
+ from .saas_client import *
@@ -0,0 +1,56 @@
1
+ import os
2
+ import requests
3
+
4
+ import pyntcli.log.log as log
5
+ from pyntcli.store import CredStore
6
+
7
+ PYNT_SAAS = os.environ.get("PYNT_SAAS_URL", "https://api.pynt.io/v1")
8
+ logger = log.get_logger()
9
+
10
+ class PyntClient:
11
+ def __init__(self, base_url=PYNT_SAAS):
12
+ self.base_url = base_url
13
+
14
+ def _get_headers(self):
15
+ headers = {}
16
+ with CredStore() as store:
17
+ access_token = store.get_access_token()
18
+ token_type = store.get_token_type()
19
+ headers["Authorization"] = f"{token_type} {access_token}"
20
+ return headers
21
+
22
+ def get_config(self):
23
+ url = f"{self.base_url}/config"
24
+ headers = self._get_headers()
25
+
26
+ try:
27
+ response = requests.get(url, headers=headers, timeout=10)
28
+ response.raise_for_status()
29
+ return response.json() # returning actual data
30
+
31
+ except requests.exceptions.HTTPError as e:
32
+ logger.error(f"HTTP error accessing '{url}': {e}")
33
+ raise e
34
+ except requests.exceptions.RequestException as e:
35
+ logger.error(f"Error accessing '{url}': {e}")
36
+
37
+ return None
38
+
39
+ def get_application_by_name(self, application_name):
40
+ url = f"{self.base_url}/application/{application_name}"
41
+ headers = self._get_headers()
42
+
43
+ try:
44
+ response = requests.get(url, headers=headers)
45
+ response.raise_for_status()
46
+ return response.json() # returning actual data
47
+
48
+ except requests.exceptions.HTTPError as e:
49
+ logger.error(f"HTTP error accessing '{url}': {e}")
50
+ raise e
51
+ except requests.exceptions.RequestException as e:
52
+ logger.error(f"Error accessing '{url}': {e}")
53
+
54
+ return None
55
+
56
+ pynt_client = PyntClient()
pyntcli/ui/pynt_errors.py CHANGED
@@ -2,14 +2,12 @@ from pyntcli.ui import ui_thread
2
2
 
3
3
 
4
4
  def unexpected_error(original):
5
- printer_text = ui_thread.PrinterText("An Unexpected Error Occurred", style=ui_thread.PrinterText.WARNING) \
6
- .with_line("")
5
+ printer_text = ui_thread.PrinterText("An Unexpected Error Occurred: ", style=ui_thread.PrinterText.WARNING)
7
6
 
8
7
  msg = str(original) or repr(original)
9
- if msg:
10
- printer_text.with_line(f"e: {msg}")
8
+ printer_text.text.append(msg if msg else "Unknown error")
11
9
 
12
- printer_text = printer_text.with_line(
10
+ printer_text = printer_text.with_line("").with_line(
13
11
  "Please tell us about it in our community channel and we will help you figure it out:",
14
12
  style=ui_thread.PrinterText.HEADER) \
15
13
  .with_line("https://join.slack.com/t/pynt-community/shared_invite/zt-1mvacojz5-WNjbH4HN8iksmKpCLTxOiQ",
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: pyntcli
3
- Version: 0.1.115
3
+ Version: 0.1.117
4
4
  Summary: Command line utility to handle all of Pynt's different integrations
5
5
  Author-email: Pynt-io <support@pynt.io>
6
6
  Project-URL: Homepage, https://pynt.io
@@ -1,12 +1,12 @@
1
1
  ignoreTests/conftest.py,sha256=gToq5K74GtgeGQXjFvXSzMaE6axBYxAzcFG5XJPOXjI,427
2
2
  ignoreTests/auth/login.py,sha256=7GeBirHTD9t6EassLYsegCw1FZHkfjvVW1Z5uybHzgM,3801
3
3
  ignoreTests/store/cred_store.py,sha256=_7-917EtNC9eKEumO2_lt-7KuDmCwOZFaowCm7DbA_A,254
4
- pyntcli/__init__.py,sha256=w7iUQrCxcREXlc0oJR5V2FHWH8-aYWfF0nTwm9iSFCY,24
4
+ pyntcli/__init__.py,sha256=tC6Ly5NZvDBZKJuC4iaO2NyJcqX7enbauSAG6rxadFU,24
5
5
  pyntcli/main.py,sha256=RD0W2_0ogYBCXubo-YewxHYkiIXxNv6NkZOh3n1VujE,5964
6
6
  pyntcli/analytics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  pyntcli/analytics/send.py,sha256=0hJ0WJNFHLqyohtRr_xOg5WEXzxHrUOlcePPg-k65Hk,3846
8
8
  pyntcli/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- pyntcli/auth/login.py,sha256=Oz1DtEZje0afgJcHSwEFHcH78X-QD5Mjn0CQ9ZgCfQU,5844
9
+ pyntcli/auth/login.py,sha256=qtdoCgWIPi3_YXehI7SVk_E8aDVhH39wGc87tlkazSE,5558
10
10
  pyntcli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  pyntcli/commands/burp.py,sha256=9kcqjC9Rgj5oZimGZuA_oO71Hn2Z3py8k5vr-eMKnUM,14317
12
12
  pyntcli/commands/command.py,sha256=ulxhWyTnuqQfyNy5somqBbQoTCvd0Hg4OnPJ8thJzAs,11078
@@ -15,7 +15,7 @@ pyntcli/commands/id_command.py,sha256=UBEgMIpm4vauTCsKyixltiGUolNg_OfHEJvJ_i5BpJ
15
15
  pyntcli/commands/listen.py,sha256=RTlUt2oq5_BPeBZpG5yQ6GPAG_Cf0JVrUrkzz8uw9ns,9042
16
16
  pyntcli/commands/newman.py,sha256=w0d0Pi1swJQ8E3oRs6vsgw_591sl-4bcLpWZwuBXmDI,5282
17
17
  pyntcli/commands/postman.py,sha256=kN1PkzPpcUnsbirg17AN9JwJZu6VBt6OeKYrLGrvtFc,4964
18
- pyntcli/commands/pynt_cmd.py,sha256=Sqb64Ow3qhhBdyAglY6wV-SSL0AK5ADoEeOHO4FniQY,7942
18
+ pyntcli/commands/pynt_cmd.py,sha256=TcsKVl0QZLEDIZjo-977IY6k4MAXVk_hljraW1eJmyg,7790
19
19
  pyntcli/commands/root.py,sha256=bTGlFroeK7WG9dAhFkVTVnpEM-Gdp8QKCuTxW_QWNlQ,4441
20
20
  pyntcli/commands/static_file_extensions.py,sha256=PZJb02BI-64tbU-j3rdCNsXzTh7gkIDGxGKbKNw3h5k,1995
21
21
  pyntcli/commands/sub_command.py,sha256=GF3-rE_qk2L4jGPFqHLm9SdGINmu3EakhjJTFyWjRms,374
@@ -24,8 +24,10 @@ pyntcli/commands/util.py,sha256=ev06aUlJ9tCSw1eAGVIsGlVVY4u0H6AJG9b5MB_bAzs,4594
24
24
  pyntcli/log/__init__.py,sha256=cOGwOYzMoshEbZiiasBGkj6wF0SBu3Jdpl-AuakDesw,19
25
25
  pyntcli/log/log.py,sha256=YXCvcCzuhQ5QUT2L02uQEdN_lTCzLEuet4OnLuEnjlM,112
26
26
  pyntcli/pynt_docker/__init__.py,sha256=PQIOVxc7XXtMLfEX7ojgwf_Z3mmTllO3ZvzUZTPOxQY,30
27
- pyntcli/pynt_docker/container_utils.py,sha256=_Onn7loInzyJAG2-Uk6CGpsuRyelmUFHOvtJj4Uzi9A,175
28
- pyntcli/pynt_docker/pynt_container.py,sha256=YiYEq8_GZ8NpFNkUV4ynSEdKaYEjE764JgjdEknSw4g,13997
27
+ pyntcli/pynt_docker/container_utils.py,sha256=DeI-uSgdcO_2rGs2dvQ5gBDNo_iKKuPIQO2D9oej5Gw,1485
28
+ pyntcli/pynt_docker/pynt_container.py,sha256=7VG7e8mCabFUJoX-AuSnxVoXtO9ben-QQdNBL5Y5z9g,13861
29
+ pyntcli/saas_client/__init__.py,sha256=HPBzoC5a6F5_WkHubcjq_W4m1OQ9i0TX8QXBtJlKm1M,26
30
+ pyntcli/saas_client/saas_client.py,sha256=7mJNo2x4Oy2N4NKdHyGRxXZUk_VHZvRu1x586rojrp0,1756
29
31
  pyntcli/store/__init__.py,sha256=1fP8cEAQCF_myja3gnhHH9FEqtBiOJ-2aBmUXSKBdFA,41
30
32
  pyntcli/store/json_connector.py,sha256=UGs3uORw3iyn0YJ8kzab-veEZToA6d-ByXYuqEleWsA,560
31
33
  pyntcli/store/store.py,sha256=Kl_HT9FJFdKlAH7SwAt3g4-bW-r-1ve_u13OPggQai0,2529
@@ -35,13 +37,13 @@ pyntcli/transport/pynt_requests.py,sha256=gOPwBpPj6qIymDRFNgcQmwoI5Rqs4GMk4pfBva
35
37
  pyntcli/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
38
  pyntcli/ui/progress.py,sha256=RrnO_jJNunoyupylakmWmHOEPw3lh99OHpKBzL6OBiE,1008
37
39
  pyntcli/ui/prompt.py,sha256=tK3BFYvgT7ZgSrsN5ASkltcsbhy8tOdNfEjRyCjOk6Q,1570
38
- pyntcli/ui/pynt_errors.py,sha256=00UprD4tFViREv7kuXGQ99PAKGTpXYixxi3Ndeoeiew,689
40
+ pyntcli/ui/pynt_errors.py,sha256=4CTUnO6D8HD4JFWwKsNqdmhp5XugfFK7wJT5TK3k-Bc,686
39
41
  pyntcli/ui/report.py,sha256=W-icPSZrGLOubXgam0LpOvHLl_aZg9Zx9qIkL8Ym5PE,1930
40
42
  pyntcli/ui/ui_thread.py,sha256=XUBgLpYQjVhrilU-ofw7VSXgTiwneSdTxm61EvC3x4Q,5091
41
43
  tests/test_utils.py,sha256=t5fTQUk1U_Js6iMxcGYGqt4C-crzOJ0CqCKtLkRtUi0,2050
42
- tests/commands/test_pynt_cmd.py,sha256=c0m7L_kK3iWaHTIEC5H0IlUSL2UUU4NdakduLDbsVyg,8505
43
- pyntcli-0.1.115.dist-info/METADATA,sha256=sZ2RGy8wdB9ZZ4HgeoY4kJddkqOAsVkOs8Y218MjMtE,427
44
- pyntcli-0.1.115.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
45
- pyntcli-0.1.115.dist-info/entry_points.txt,sha256=kcGmqAxXDttNk2EPRcqunc_LTVp61gzakz0v-GEE2SY,43
46
- pyntcli-0.1.115.dist-info/top_level.txt,sha256=64XSgBzSpgwjYjEKHZE7q3JH2a816zEeyZBXfJi3AKI,42
47
- pyntcli-0.1.115.dist-info/RECORD,,
44
+ tests/commands/test_pynt_cmd.py,sha256=J4JrEuD_qSVN76Fu6bKRjrxWSwCTXVEAzVPYdXMa0tI,8826
45
+ pyntcli-0.1.117.dist-info/METADATA,sha256=R8P0CNK4GXBEwOB-ky2Qxu9lHrURd-eogrp1lIF3pwo,427
46
+ pyntcli-0.1.117.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
47
+ pyntcli-0.1.117.dist-info/entry_points.txt,sha256=kcGmqAxXDttNk2EPRcqunc_LTVp61gzakz0v-GEE2SY,43
48
+ pyntcli-0.1.117.dist-info/top_level.txt,sha256=64XSgBzSpgwjYjEKHZE7q3JH2a816zEeyZBXfJi3AKI,42
49
+ pyntcli-0.1.117.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -8,18 +8,16 @@ import requests
8
8
 
9
9
  class TestIsBusinessPlanUser(unittest.TestCase):
10
10
 
11
- @patch('pyntcli.commands.pynt_cmd.requests.get')
12
- @patch('pyntcli.commands.pynt_cmd.CredStore')
13
- def test_is_business_plan_user_success(self, mock_cred_store, mock_requests_get):
11
+ @patch('requests.get')
12
+ @patch('pyntcli.saas_client.saas_client.CredStore')
13
+ def test_is_business_plan_user_success(self, mock_requests_get, mock_cred_store):
14
14
  # Mock the CredStore context manager
15
- mock_store_instance = MagicMock()
15
+ mock_store_instance = mock_cred_store.return_value.__enter__.return_value
16
16
  mock_store_instance.get_access_token.return_value = 'fake_token'
17
17
  mock_store_instance.get_token_type.return_value = 'Bearer'
18
- mock_cred_store.return_value.__enter__.return_value = mock_store_instance
19
18
 
20
19
  # Mock the requests.get response
21
20
  mock_response = MagicMock()
22
- mock_response.status_code = 200
23
21
  mock_requests_get.return_value = mock_response
24
22
 
25
23
  # Instantiate the class and call the method
@@ -29,18 +27,18 @@ class TestIsBusinessPlanUser(unittest.TestCase):
29
27
  # Assert the result
30
28
  self.assertTrue(result)
31
29
 
32
- @patch('pyntcli.commands.pynt_cmd.requests.get')
33
- @patch('pyntcli.commands.pynt_cmd.CredStore')
34
- def test_is_business_plan_user_failure(self, mock_cred_store, mock_requests_get):
30
+ @patch('requests.get')
31
+ @patch('pyntcli.saas_client.saas_client.CredStore')
32
+ def test_is_business_plan_user_failure(self,mock_cred_store, mock_requests_get):
35
33
  # Mock the CredStore context manager
36
- mock_store_instance = MagicMock()
34
+ mock_store_instance = mock_cred_store.return_value.__enter__.return_value
37
35
  mock_store_instance.get_access_token.return_value = 'fake_token'
38
36
  mock_store_instance.get_token_type.return_value = 'Bearer'
39
- mock_cred_store.return_value.__enter__.return_value = mock_store_instance
37
+
40
38
 
41
39
  # Mock the requests.get response
42
40
  mock_response = MagicMock()
43
- mock_response.status_code = 403
41
+ mock_response.raise_for_status.side_effect = requests.exceptions.HTTPError(response=MagicMock(status_code=403))
44
42
  mock_requests_get.return_value = mock_response
45
43
 
46
44
  # Instantiate the class and call the method
@@ -50,14 +48,13 @@ class TestIsBusinessPlanUser(unittest.TestCase):
50
48
  # Assert the result
51
49
  self.assertFalse(result)
52
50
 
53
- @patch('pyntcli.commands.pynt_cmd.requests.get')
54
- @patch('pyntcli.commands.pynt_cmd.CredStore')
51
+ @patch('requests.get')
52
+ @patch('pyntcli.saas_client.saas_client.CredStore')
55
53
  def test_is_business_plan_user_exception(self, mock_cred_store, mock_requests_get):
56
54
  # Mock the CredStore context manager
57
- mock_store_instance = MagicMock()
55
+ mock_store_instance = mock_cred_store.return_value.__enter__.return_value
58
56
  mock_store_instance.get_access_token.return_value = 'fake_token'
59
57
  mock_store_instance.get_token_type.return_value = 'Bearer'
60
- mock_cred_store.return_value.__enter__.return_value = mock_store_instance
61
58
 
62
59
  # Mock the requests.get to raise an exception
63
60
  mock_requests_get.side_effect = requests.exceptions.RequestException
@@ -137,6 +134,18 @@ class TestIsBusinessPlanUser(unittest.TestCase):
137
134
  # Assert the result
138
135
  self.assertTrue(result)
139
136
 
137
+ @patch('pyntcli.commands.pynt_cmd.prompt.confirmation_prompt_with_timeout', return_value=True)
138
+ @patch('requests.get')
139
+ def test_is_auto_create_app_confirmed_auto_confirms(self, mock_requests_get, _):
140
+ mock_response = MagicMock()
141
+ mock_requests_get.return_value = mock_response
142
+
143
+ instance = PyntCommand()
144
+ result = instance._is_auto_create_app_confirmed("app_name")
145
+
146
+ # Assert the result
147
+ self.assertTrue(result)
148
+
140
149
  @patch('pyntcli.commands.pynt_cmd.prompt.confirmation_prompt_with_timeout', return_value=False)
141
150
  @patch('pyntcli.commands.pynt_cmd.StateStore')
142
151
  def test_missing_app_id_confirmation_confirmation_expired_user_aborts(self, mock_state_store, _):