deepctl-cmd-debug-network 0.1.12__tar.gz → 0.5.0__tar.gz
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.
- {deepctl_cmd_debug_network-0.1.12 → deepctl_cmd_debug_network-0.5.0}/PKG-INFO +11 -12
- {deepctl_cmd_debug_network-0.1.12 → deepctl_cmd_debug_network-0.5.0}/README.md +4 -5
- {deepctl_cmd_debug_network-0.1.12 → deepctl_cmd_debug_network-0.5.0}/pyproject.toml +11 -7
- {deepctl_cmd_debug_network-0.1.12 → deepctl_cmd_debug_network-0.5.0}/src/deepctl_cmd_debug_network/command.py +136 -54
- {deepctl_cmd_debug_network-0.1.12 → deepctl_cmd_debug_network-0.5.0}/src/deepctl_cmd_debug_network/models.py +3 -1
- {deepctl_cmd_debug_network-0.1.12 → deepctl_cmd_debug_network-0.5.0}/src/deepctl_cmd_debug_network.egg-info/PKG-INFO +11 -12
- deepctl_cmd_debug_network-0.5.0/src/deepctl_cmd_debug_network.egg-info/requires.txt +6 -0
- deepctl_cmd_debug_network-0.1.12/src/deepctl_cmd_debug_network.egg-info/requires.txt +0 -6
- {deepctl_cmd_debug_network-0.1.12 → deepctl_cmd_debug_network-0.5.0}/setup.cfg +0 -0
- {deepctl_cmd_debug_network-0.1.12 → deepctl_cmd_debug_network-0.5.0}/src/deepctl_cmd_debug_network/__init__.py +0 -0
- {deepctl_cmd_debug_network-0.1.12 → deepctl_cmd_debug_network-0.5.0}/src/deepctl_cmd_debug_network.egg-info/SOURCES.txt +0 -0
- {deepctl_cmd_debug_network-0.1.12 → deepctl_cmd_debug_network-0.5.0}/src/deepctl_cmd_debug_network.egg-info/dependency_links.txt +0 -0
- {deepctl_cmd_debug_network-0.1.12 → deepctl_cmd_debug_network-0.5.0}/src/deepctl_cmd_debug_network.egg-info/entry_points.txt +0 -0
- {deepctl_cmd_debug_network-0.1.12 → deepctl_cmd_debug_network-0.5.0}/src/deepctl_cmd_debug_network.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepctl-cmd-debug-network
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Network debug subcommand for deepctl
|
|
5
5
|
Author-email: Deepgram <devrel@deepgram.com>
|
|
6
6
|
Maintainer-email: Deepgram <devrel@deepgram.com>
|
|
@@ -14,12 +14,12 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
15
|
Requires-Python: >=3.10
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
|
-
Requires-Dist: deepctl
|
|
18
|
-
Requires-Dist:
|
|
19
|
-
Requires-Dist:
|
|
20
|
-
Requires-Dist:
|
|
21
|
-
Requires-Dist:
|
|
22
|
-
Requires-Dist:
|
|
17
|
+
Requires-Dist: deepctl==0.5.0
|
|
18
|
+
Requires-Dist: deepctl-core==0.5.0
|
|
19
|
+
Requires-Dist: click<9,>=8.2.0
|
|
20
|
+
Requires-Dist: rich<16,>=13.0.0
|
|
21
|
+
Requires-Dist: pydantic<3,>=2.0.0
|
|
22
|
+
Requires-Dist: httpx<1,>=0.24.0
|
|
23
23
|
|
|
24
24
|
# deepctl-cmd-debug-network
|
|
25
25
|
|
|
@@ -58,11 +58,10 @@ pipx run deepctl --help
|
|
|
58
58
|
|
|
59
59
|
## Dependencies
|
|
60
60
|
|
|
61
|
-
- `click>=8.
|
|
62
|
-
- `rich>=13.0.0`
|
|
63
|
-
- `pydantic>=2.0.0`
|
|
64
|
-
- `httpx>=0.24.0`
|
|
65
|
-
- `requests>=2.31,<3.0`
|
|
61
|
+
- `click>=8.2.0,<9`
|
|
62
|
+
- `rich>=13.0.0,<16`
|
|
63
|
+
- `pydantic>=2.0.0,<3`
|
|
64
|
+
- `httpx>=0.24.0,<1`
|
|
66
65
|
|
|
67
66
|
## License
|
|
68
67
|
|
|
@@ -35,11 +35,10 @@ pipx run deepctl --help
|
|
|
35
35
|
|
|
36
36
|
## Dependencies
|
|
37
37
|
|
|
38
|
-
- `click>=8.
|
|
39
|
-
- `rich>=13.0.0`
|
|
40
|
-
- `pydantic>=2.0.0`
|
|
41
|
-
- `httpx>=0.24.0`
|
|
42
|
-
- `requests>=2.31,<3.0`
|
|
38
|
+
- `click>=8.2.0,<9`
|
|
39
|
+
- `rich>=13.0.0,<16`
|
|
40
|
+
- `pydantic>=2.0.0,<3`
|
|
41
|
+
- `httpx>=0.24.0,<1`
|
|
43
42
|
|
|
44
43
|
## License
|
|
45
44
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "deepctl-cmd-debug-network"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.5.0" # x-release-please-version
|
|
8
8
|
description = "Network debug subcommand for deepctl"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -21,12 +21,12 @@ classifiers = [
|
|
|
21
21
|
keywords = ["deepgram", "cli", "debug", "network", "diagnostics"]
|
|
22
22
|
requires-python = ">=3.10"
|
|
23
23
|
dependencies = [
|
|
24
|
-
"deepctl
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
24
|
+
"deepctl==0.5.0", # x-release-please-version
|
|
25
|
+
"deepctl-core==0.5.0", # x-release-please-version
|
|
26
|
+
"click>=8.2.0,<9",
|
|
27
|
+
"rich>=13.0.0,<16",
|
|
28
|
+
"pydantic>=2.0.0,<3",
|
|
29
|
+
"httpx>=0.24.0,<1",
|
|
30
30
|
]
|
|
31
31
|
|
|
32
32
|
[project.scripts]
|
|
@@ -41,3 +41,7 @@ package-dir = { "" = "src" }
|
|
|
41
41
|
[tool.setuptools.packages.find]
|
|
42
42
|
where = ["src"]
|
|
43
43
|
include = ["deepctl_cmd_debug_network*"]
|
|
44
|
+
|
|
45
|
+
[tool.uv.sources]
|
|
46
|
+
deepctl = { workspace = true }
|
|
47
|
+
deepctl-core = { workspace = true }
|
|
@@ -6,12 +6,9 @@ import socket
|
|
|
6
6
|
import subprocess
|
|
7
7
|
import sys
|
|
8
8
|
import time
|
|
9
|
-
import
|
|
10
|
-
from typing import Any
|
|
9
|
+
from typing import TYPE_CHECKING, Any
|
|
11
10
|
from urllib.parse import urlparse
|
|
12
11
|
|
|
13
|
-
import requests
|
|
14
|
-
import urllib3
|
|
15
12
|
from deepctl_core import AuthManager, BaseCommand, Config, DeepgramClient
|
|
16
13
|
from rich.console import Console
|
|
17
14
|
from rich.panel import Panel
|
|
@@ -28,18 +25,92 @@ from .models import (
|
|
|
28
25
|
TLSTestResult,
|
|
29
26
|
)
|
|
30
27
|
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
import ssl
|
|
30
|
+
|
|
31
|
+
import httpx
|
|
32
|
+
|
|
31
33
|
console = Console()
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
|
|
36
|
+
def _default_host() -> str:
|
|
37
|
+
"""The Deepgram API host (``hosts.DEFAULT_BASE_URL``, via the Transport).
|
|
38
|
+
|
|
39
|
+
The default endpoint only: this command sends no credentials anywhere.
|
|
40
|
+
"""
|
|
41
|
+
from deepctl_core import transport
|
|
42
|
+
|
|
43
|
+
return transport.default_host()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _is_ssl_error(exc: BaseException) -> bool:
|
|
47
|
+
"""True when an httpx error was caused by a TLS failure (the case
|
|
48
|
+
requests raised as SSLError)."""
|
|
49
|
+
import ssl
|
|
50
|
+
|
|
51
|
+
seen: set[int] = set()
|
|
52
|
+
current: BaseException | None = exc
|
|
53
|
+
while current is not None and id(current) not in seen:
|
|
54
|
+
if isinstance(current, ssl.SSLError):
|
|
55
|
+
return True
|
|
56
|
+
seen.add(id(current))
|
|
57
|
+
current = current.__cause__ or current.__context__
|
|
58
|
+
return False
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _requests_ca_bundle() -> str | None:
|
|
62
|
+
"""The CA bundle requests would have used from the environment.
|
|
63
|
+
|
|
64
|
+
httpx reads SSL_CERT_FILE and SSL_CERT_DIR itself; when either is set it
|
|
65
|
+
wins. Otherwise REQUESTS_CA_BUNDLE, then CURL_CA_BUNDLE, as requests
|
|
66
|
+
resolved them (an empty value counts as unset).
|
|
67
|
+
"""
|
|
68
|
+
if os.environ.get("SSL_CERT_FILE") or os.environ.get("SSL_CERT_DIR"):
|
|
69
|
+
return None
|
|
70
|
+
return (
|
|
71
|
+
os.environ.get("REQUESTS_CA_BUNDLE") or os.environ.get("CURL_CA_BUNDLE") or None
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _verify_setting(verify: bool) -> "bool | ssl.SSLContext":
|
|
76
|
+
"""httpx's verify argument: False stays False; True becomes an SSL
|
|
77
|
+
context on the requests-style bundle when one is set in the
|
|
78
|
+
environment, and otherwise stays True (httpx defaults, which honour
|
|
79
|
+
SSL_CERT_FILE / SSL_CERT_DIR)."""
|
|
80
|
+
import ssl
|
|
81
|
+
|
|
82
|
+
if not verify:
|
|
83
|
+
return False
|
|
84
|
+
bundle = _requests_ca_bundle()
|
|
85
|
+
if bundle is None:
|
|
86
|
+
return True
|
|
87
|
+
if os.path.isdir(bundle):
|
|
88
|
+
return ssl.create_default_context(capath=bundle)
|
|
89
|
+
if not os.path.isfile(bundle):
|
|
90
|
+
# requests' wording for the same mistake.
|
|
91
|
+
raise OSError(
|
|
92
|
+
"Could not find a suitable TLS CA certificate bundle, "
|
|
93
|
+
f"invalid path: {bundle}"
|
|
94
|
+
)
|
|
95
|
+
return ssl.create_default_context(cafile=bundle)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _dist_version(name: str) -> str:
|
|
99
|
+
"""Installed version of a distribution, read without importing it."""
|
|
100
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
101
|
+
|
|
102
|
+
try:
|
|
103
|
+
return version(name)
|
|
104
|
+
except PackageNotFoundError:
|
|
105
|
+
return "not installed"
|
|
38
106
|
|
|
39
107
|
|
|
40
108
|
class NetworkCommand(BaseCommand):
|
|
41
109
|
"""Debug network connectivity issues with Deepgram services."""
|
|
42
110
|
|
|
111
|
+
# Tests swap in an httpx.MockTransport; None means the real network.
|
|
112
|
+
_transport: "httpx.BaseTransport | None" = None
|
|
113
|
+
|
|
43
114
|
name = "network"
|
|
44
115
|
help = "Debug network connectivity issues with Deepgram services"
|
|
45
116
|
short_help = "Debug network issues"
|
|
@@ -64,7 +135,7 @@ class NetworkCommand(BaseCommand):
|
|
|
64
135
|
return [
|
|
65
136
|
{
|
|
66
137
|
"names": ["--endpoint", "-e"],
|
|
67
|
-
"help":
|
|
138
|
+
"help": f"Specific endpoint to test (default: {_default_host()})",
|
|
68
139
|
"type": str,
|
|
69
140
|
"is_option": True,
|
|
70
141
|
},
|
|
@@ -107,6 +178,29 @@ class NetworkCommand(BaseCommand):
|
|
|
107
178
|
},
|
|
108
179
|
]
|
|
109
180
|
|
|
181
|
+
def _http_client(
|
|
182
|
+
self, *, timeout: float, verify: bool = True, follow_redirects: bool = False
|
|
183
|
+
) -> "httpx.Client":
|
|
184
|
+
"""A throwaway client for one diagnostic request.
|
|
185
|
+
|
|
186
|
+
Never the shared CLI client: it carries no credentials (httpx does
|
|
187
|
+
not read ~/.netrc), and a verify=False client must not outlive its
|
|
188
|
+
one test. trust_env applies HTTP(S)_PROXY / NO_PROXY as requests did.
|
|
189
|
+
|
|
190
|
+
CA trust, first match wins (verify=False skips all of it):
|
|
191
|
+
SSL_CERT_FILE or SSL_CERT_DIR (read by httpx), then
|
|
192
|
+
REQUESTS_CA_BUNDLE, then CURL_CA_BUNDLE, then httpx's default bundle.
|
|
193
|
+
"""
|
|
194
|
+
import httpx
|
|
195
|
+
|
|
196
|
+
return httpx.Client(
|
|
197
|
+
timeout=timeout,
|
|
198
|
+
verify=_verify_setting(verify),
|
|
199
|
+
follow_redirects=follow_redirects,
|
|
200
|
+
trust_env=True,
|
|
201
|
+
transport=self._transport,
|
|
202
|
+
)
|
|
203
|
+
|
|
110
204
|
def handle(
|
|
111
205
|
self,
|
|
112
206
|
config: Config,
|
|
@@ -115,7 +209,7 @@ class NetworkCommand(BaseCommand):
|
|
|
115
209
|
**kwargs: Any,
|
|
116
210
|
) -> Any:
|
|
117
211
|
"""Handle network debug command execution."""
|
|
118
|
-
endpoint = kwargs.get("endpoint") or
|
|
212
|
+
endpoint = kwargs.get("endpoint") or _default_host()
|
|
119
213
|
verbose = kwargs.get("verbose", False)
|
|
120
214
|
skip_commands = kwargs.get("skip_commands", False)
|
|
121
215
|
timeout = kwargs.get("timeout", 10)
|
|
@@ -171,7 +265,7 @@ class NetworkCommand(BaseCommand):
|
|
|
171
265
|
progress.remove_task(task)
|
|
172
266
|
|
|
173
267
|
# 5. Python requests tests
|
|
174
|
-
task = progress.add_task("Testing Python
|
|
268
|
+
task = progress.add_task("Testing Python HTTP client...", total=None)
|
|
175
269
|
self._test_python_requests(endpoint, result, timeout)
|
|
176
270
|
progress.remove_task(task)
|
|
177
271
|
|
|
@@ -213,8 +307,9 @@ class NetworkCommand(BaseCommand):
|
|
|
213
307
|
result.environment_info = {
|
|
214
308
|
"python_version": sys.version,
|
|
215
309
|
"platform": sys.platform,
|
|
216
|
-
"requests_version": requests
|
|
217
|
-
"urllib3_version":
|
|
310
|
+
"requests_version": _dist_version("requests"),
|
|
311
|
+
"urllib3_version": _dist_version("urllib3"),
|
|
312
|
+
"httpx_version": _dist_version("httpx"),
|
|
218
313
|
"proxy_env_vars": {
|
|
219
314
|
"http_proxy": os.environ.get("http_proxy", "Not set"),
|
|
220
315
|
"https_proxy": os.environ.get("https_proxy", "Not set"),
|
|
@@ -270,20 +365,19 @@ class NetworkCommand(BaseCommand):
|
|
|
270
365
|
|
|
271
366
|
try:
|
|
272
367
|
start_time = time.time()
|
|
273
|
-
|
|
274
|
-
f"https://{hostname}/"
|
|
275
|
-
)
|
|
368
|
+
with self._http_client(timeout=timeout) as http:
|
|
369
|
+
response = http.get(f"https://{hostname}/")
|
|
276
370
|
endpoint_test.response_time_ms = (time.time() - start_time) * 1000
|
|
277
371
|
endpoint_test.status_code = response.status_code
|
|
278
372
|
endpoint_test.reachable = True
|
|
279
373
|
endpoint_test.ssl_valid = True
|
|
280
374
|
|
|
281
|
-
except requests.exceptions.SSLError as e:
|
|
282
|
-
endpoint_test.error = f"SSL Error: {e!s}"
|
|
283
|
-
endpoint_test.ssl_valid = False
|
|
284
|
-
result.network_issues_detected = True
|
|
285
375
|
except Exception as e:
|
|
286
|
-
|
|
376
|
+
if _is_ssl_error(e):
|
|
377
|
+
endpoint_test.error = f"SSL Error: {e!s}"
|
|
378
|
+
endpoint_test.ssl_valid = False
|
|
379
|
+
else:
|
|
380
|
+
endpoint_test.error = str(e)
|
|
287
381
|
result.network_issues_detected = True
|
|
288
382
|
|
|
289
383
|
result.endpoint_results.append(endpoint_test)
|
|
@@ -446,7 +540,8 @@ class NetworkCommand(BaseCommand):
|
|
|
446
540
|
else:
|
|
447
541
|
try:
|
|
448
542
|
start_time = time.time()
|
|
449
|
-
|
|
543
|
+
with self._http_client(timeout=5, follow_redirects=True) as http:
|
|
544
|
+
response = http.head(url)
|
|
450
545
|
endpoint_test.response_time_ms = (time.time() - start_time) * 1000
|
|
451
546
|
endpoint_test.status_code = response.status_code
|
|
452
547
|
endpoint_test.accessible = response.status_code < 400
|
|
@@ -460,7 +555,8 @@ class NetworkCommand(BaseCommand):
|
|
|
460
555
|
def _test_python_requests(
|
|
461
556
|
self, hostname: str, result: NetworkDebugResult, timeout: int
|
|
462
557
|
) -> None:
|
|
463
|
-
"""Test connectivity
|
|
558
|
+
"""Test connectivity with Python's HTTP client (httpx), with and
|
|
559
|
+
without certificate verification. Each request gets its own client."""
|
|
464
560
|
# Test with SSL verification enabled
|
|
465
561
|
test_with_verify = PythonRequestsTest(
|
|
466
562
|
url=f"https://{hostname}/", success=False, ssl_verify_enabled=True
|
|
@@ -468,21 +564,18 @@ class NetworkCommand(BaseCommand):
|
|
|
468
564
|
|
|
469
565
|
try:
|
|
470
566
|
start_time = time.time()
|
|
471
|
-
|
|
472
|
-
f"https://{hostname}/"
|
|
473
|
-
timeout=timeout,
|
|
474
|
-
verify=True,
|
|
475
|
-
allow_redirects=False,
|
|
476
|
-
)
|
|
567
|
+
with self._http_client(timeout=timeout, verify=True) as http:
|
|
568
|
+
response = http.get(f"https://{hostname}/")
|
|
477
569
|
test_with_verify.response_time_ms = (time.time() - start_time) * 1000
|
|
478
570
|
test_with_verify.status_code = response.status_code
|
|
479
571
|
test_with_verify.success = True
|
|
480
572
|
|
|
481
|
-
except requests.exceptions.SSLError as e:
|
|
482
|
-
test_with_verify.error = f"SSL verification failed: {e!s}"
|
|
483
|
-
result.network_issues_detected = True
|
|
484
573
|
except Exception as e:
|
|
485
|
-
|
|
574
|
+
if _is_ssl_error(e):
|
|
575
|
+
test_with_verify.error = f"SSL verification failed: {e!s}"
|
|
576
|
+
result.network_issues_detected = True
|
|
577
|
+
else:
|
|
578
|
+
test_with_verify.error = str(e)
|
|
486
579
|
|
|
487
580
|
result.python_requests_tests.append(test_with_verify)
|
|
488
581
|
|
|
@@ -492,25 +585,17 @@ class NetworkCommand(BaseCommand):
|
|
|
492
585
|
)
|
|
493
586
|
|
|
494
587
|
try:
|
|
495
|
-
#
|
|
496
|
-
|
|
497
|
-
|
|
588
|
+
# An isolated, credential-free client that is closed right after
|
|
589
|
+
# this one request; nothing else ever sees verify=False.
|
|
498
590
|
start_time = time.time()
|
|
499
|
-
|
|
500
|
-
f"https://{hostname}/"
|
|
501
|
-
timeout=timeout,
|
|
502
|
-
verify=False,
|
|
503
|
-
allow_redirects=False,
|
|
504
|
-
)
|
|
591
|
+
with self._http_client(timeout=timeout, verify=False) as http:
|
|
592
|
+
response = http.get(f"https://{hostname}/")
|
|
505
593
|
test_without_verify.response_time_ms = (time.time() - start_time) * 1000
|
|
506
594
|
test_without_verify.status_code = response.status_code
|
|
507
595
|
test_without_verify.success = True
|
|
508
596
|
|
|
509
597
|
except Exception as e:
|
|
510
598
|
test_without_verify.error = str(e)
|
|
511
|
-
finally:
|
|
512
|
-
# Re-enable warnings
|
|
513
|
-
warnings.resetwarnings()
|
|
514
599
|
|
|
515
600
|
result.python_requests_tests.append(test_without_verify)
|
|
516
601
|
|
|
@@ -663,7 +748,7 @@ class NetworkCommand(BaseCommand):
|
|
|
663
748
|
) -> None:
|
|
664
749
|
"""Test latency to known Deepgram endpoints."""
|
|
665
750
|
endpoints = [
|
|
666
|
-
(
|
|
751
|
+
(_default_host(), "Primary API"),
|
|
667
752
|
]
|
|
668
753
|
|
|
669
754
|
console.print("\n[bold]Multi-Region Latency:[/bold]")
|
|
@@ -694,11 +779,8 @@ class NetworkCommand(BaseCommand):
|
|
|
694
779
|
|
|
695
780
|
# HTTPS connection timing
|
|
696
781
|
connect_start = time.time()
|
|
697
|
-
|
|
698
|
-
f"https://{hostname}/"
|
|
699
|
-
timeout=timeout,
|
|
700
|
-
allow_redirects=False,
|
|
701
|
-
)
|
|
782
|
+
with self._http_client(timeout=timeout) as http:
|
|
783
|
+
resp = http.get(f"https://{hostname}/")
|
|
702
784
|
total_ms = (time.time() - connect_start) * 1000
|
|
703
785
|
connect_ms = total_ms - dns_ms if total_ms and dns_ms else None
|
|
704
786
|
tls_ms = connect_ms * 0.6 if connect_ms else None
|
|
@@ -845,7 +927,7 @@ class NetworkCommand(BaseCommand):
|
|
|
845
927
|
|
|
846
928
|
# Python Requests Tests
|
|
847
929
|
if result.python_requests_tests:
|
|
848
|
-
console.print("[bold]Python
|
|
930
|
+
console.print("[bold]Python HTTP Client Tests (httpx):[/bold]")
|
|
849
931
|
for test in result.python_requests_tests:
|
|
850
932
|
verify_status = (
|
|
851
933
|
"with SSL verification"
|
|
@@ -976,7 +1058,7 @@ class NetworkCommand(BaseCommand):
|
|
|
976
1058
|
recommendations.append(
|
|
977
1059
|
"ℹ️ Proxy configuration detected. Ensure your proxy allows access to:"
|
|
978
1060
|
)
|
|
979
|
-
recommendations.append(" •
|
|
1061
|
+
recommendations.append(f" • {_default_host()} (port 443)")
|
|
980
1062
|
recommendations.append(" • Certificate validation endpoints (port 80)")
|
|
981
1063
|
|
|
982
1064
|
# Display recommendations
|
|
@@ -70,9 +70,11 @@ class TLSTestResult(BaseModel):
|
|
|
70
70
|
|
|
71
71
|
|
|
72
72
|
class PythonRequestsTest(BaseModel):
|
|
73
|
-
"""Result of
|
|
73
|
+
"""Result of one Python HTTP client request (the payload keeps its
|
|
74
|
+
requests-era name; ``library`` says which client made it)."""
|
|
74
75
|
|
|
75
76
|
url: str
|
|
77
|
+
library: str = "httpx"
|
|
76
78
|
success: bool
|
|
77
79
|
status_code: int | None = None
|
|
78
80
|
response_time_ms: float | None = None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepctl-cmd-debug-network
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Network debug subcommand for deepctl
|
|
5
5
|
Author-email: Deepgram <devrel@deepgram.com>
|
|
6
6
|
Maintainer-email: Deepgram <devrel@deepgram.com>
|
|
@@ -14,12 +14,12 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
15
|
Requires-Python: >=3.10
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
|
-
Requires-Dist: deepctl
|
|
18
|
-
Requires-Dist:
|
|
19
|
-
Requires-Dist:
|
|
20
|
-
Requires-Dist:
|
|
21
|
-
Requires-Dist:
|
|
22
|
-
Requires-Dist:
|
|
17
|
+
Requires-Dist: deepctl==0.5.0
|
|
18
|
+
Requires-Dist: deepctl-core==0.5.0
|
|
19
|
+
Requires-Dist: click<9,>=8.2.0
|
|
20
|
+
Requires-Dist: rich<16,>=13.0.0
|
|
21
|
+
Requires-Dist: pydantic<3,>=2.0.0
|
|
22
|
+
Requires-Dist: httpx<1,>=0.24.0
|
|
23
23
|
|
|
24
24
|
# deepctl-cmd-debug-network
|
|
25
25
|
|
|
@@ -58,11 +58,10 @@ pipx run deepctl --help
|
|
|
58
58
|
|
|
59
59
|
## Dependencies
|
|
60
60
|
|
|
61
|
-
- `click>=8.
|
|
62
|
-
- `rich>=13.0.0`
|
|
63
|
-
- `pydantic>=2.0.0`
|
|
64
|
-
- `httpx>=0.24.0`
|
|
65
|
-
- `requests>=2.31,<3.0`
|
|
61
|
+
- `click>=8.2.0,<9`
|
|
62
|
+
- `rich>=13.0.0,<16`
|
|
63
|
+
- `pydantic>=2.0.0,<3`
|
|
64
|
+
- `httpx>=0.24.0,<1`
|
|
66
65
|
|
|
67
66
|
## License
|
|
68
67
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|