kstlib 1.0.2__tar.gz → 1.1.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.
- {kstlib-1.0.2/src/kstlib.egg-info → kstlib-1.1.0}/PKG-INFO +7 -2
- {kstlib-1.0.2 → kstlib-1.1.0}/pyproject.toml +24 -1
- kstlib-1.1.0/src/kstlib/cli/commands/rapi/list.py +261 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/kstlib.conf.yml +11 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/meta.py +1 -1
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/rapi/__init__.py +8 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/rapi/client.py +51 -2
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/rapi/config.py +563 -25
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/rapi/exceptions.py +164 -0
- {kstlib-1.0.2 → kstlib-1.1.0/src/kstlib.egg-info}/PKG-INFO +7 -2
- kstlib-1.0.2/src/kstlib/cli/commands/rapi/list.py +0 -99
- {kstlib-1.0.2 → kstlib-1.1.0}/LICENSE.md +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/MANIFEST.in +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/README.md +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/setup.cfg +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/__main__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/alerts/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/alerts/channels/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/alerts/channels/base.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/alerts/channels/email.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/alerts/channels/slack.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/alerts/exceptions.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/alerts/manager.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/alerts/models.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/alerts/throttle.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/auth/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/auth/callback.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/auth/config.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/auth/errors.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/auth/models.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/auth/providers/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/auth/providers/base.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/auth/providers/oauth2.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/auth/providers/oidc.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/auth/session.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/auth/token.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cache/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cache/decorator.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cache/strategies.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/app.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/auth/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/auth/common.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/auth/login.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/auth/logout.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/auth/providers.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/auth/status.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/auth/token.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/auth/whoami.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/config.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/ops/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/ops/attach.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/ops/common.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/ops/list_sessions.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/ops/logs.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/ops/start.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/ops/status.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/ops/stop.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/rapi/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/rapi/call.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/rapi/show.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/secrets/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/secrets/common.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/secrets/decrypt.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/secrets/doctor.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/secrets/encrypt.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/commands/secrets/shred.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/cli/common.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/config/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/config/exceptions.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/config/export.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/config/loader.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/config/sops.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/db/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/db/aiosqlcipher.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/db/cipher.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/db/database.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/db/exceptions.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/db/pool.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/helpers/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/helpers/exceptions.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/helpers/time_trigger.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/limits.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/logging/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/logging/manager.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/mail/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/mail/builder.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/mail/exceptions.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/mail/filesystem.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/mail/transport.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/mail/transports/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/mail/transports/gmail.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/mail/transports/resend.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/mail/transports/smtp.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/metrics/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/metrics/decorators.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/metrics/exceptions.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/monitoring/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/monitoring/_styles.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/monitoring/cell.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/monitoring/config.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/monitoring/delivery.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/monitoring/exceptions.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/monitoring/image.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/monitoring/kv.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/monitoring/list.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/monitoring/metric.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/monitoring/monitoring.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/monitoring/renderer.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/monitoring/service.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/monitoring/table.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/monitoring/types.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/ops/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/ops/base.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/ops/container.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/ops/exceptions.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/ops/manager.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/ops/models.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/ops/tmux.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/ops/validators.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/py.typed +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/rapi/credentials.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/resilience/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/resilience/circuit_breaker.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/resilience/exceptions.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/resilience/heartbeat.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/resilience/rate_limiter.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/resilience/shutdown.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/resilience/watchdog.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/secrets/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/secrets/exceptions.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/secrets/models.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/secrets/providers/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/secrets/providers/base.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/secrets/providers/environment.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/secrets/providers/keyring.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/secrets/providers/kms.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/secrets/providers/kwargs.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/secrets/providers/sops.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/secrets/resolver.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/secrets/sensitive.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/secure/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/secure/fs.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/secure/permissions.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/ssl.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/ui/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/ui/exceptions.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/ui/panels.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/ui/spinner.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/ui/tables.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/utils/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/utils/dict.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/utils/formatting.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/utils/http_trace.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/utils/lazy.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/utils/secure_delete.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/utils/serialization.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/utils/text.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/utils/validators.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/websocket/__init__.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/websocket/exceptions.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/websocket/manager.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib/websocket/models.py +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib.egg-info/SOURCES.txt +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib.egg-info/dependency_links.txt +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib.egg-info/entry_points.txt +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib.egg-info/requires.txt +0 -0
- {kstlib-1.0.2 → kstlib-1.1.0}/src/kstlib.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kstlib
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: Config-driven helpers for Python projects (dynamic config, secure secrets, preset logging, and more…)
|
|
5
5
|
Author-email: Michel TRUONG <michel.truong@gmail.com>
|
|
6
6
|
Maintainer-email: Michel TRUONG <michel.truong@gmail.com>
|
|
@@ -9,15 +9,20 @@ Project-URL: Homepage, https://github.com/KaminoU/kstlib
|
|
|
9
9
|
Project-URL: Repository, https://github.com/KaminoU/kstlib
|
|
10
10
|
Project-URL: Bug Tracker, https://github.com/KaminoU/kstlib/issues
|
|
11
11
|
Project-URL: Changelog, https://github.com/KaminoU/kstlib/blob/main/CHANGELOG.md
|
|
12
|
-
Keywords: kstlib
|
|
12
|
+
Keywords: kstlib,config,configuration,yaml,secrets,sops,logging,oauth2,oidc,rest-api,http-client,resilience,circuit-breaker,rate-limiter,websocket,alerts,toolkit
|
|
13
13
|
Classifier: Development Status :: 5 - Production/Stable
|
|
14
|
+
Classifier: Environment :: Console
|
|
14
15
|
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
15
17
|
Classifier: Programming Language :: Python :: 3
|
|
16
18
|
Classifier: Programming Language :: Python :: 3.10
|
|
17
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
21
|
Classifier: Programming Language :: Python :: 3.13
|
|
20
22
|
Classifier: Programming Language :: Python :: 3.14
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Classifier: Topic :: System :: Systems Administration
|
|
25
|
+
Classifier: Typing :: Typed
|
|
21
26
|
Requires-Python: >=3.10
|
|
22
27
|
Description-Content-Type: text/markdown
|
|
23
28
|
License-File: LICENSE.md
|
|
@@ -10,7 +10,25 @@ description = "Config-driven helpers for Python projects (dynamic config, secure
|
|
|
10
10
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
11
11
|
license = "MIT"
|
|
12
12
|
license-files = ["LICENSE.md"]
|
|
13
|
-
keywords = [
|
|
13
|
+
keywords = [
|
|
14
|
+
"kstlib",
|
|
15
|
+
"config",
|
|
16
|
+
"configuration",
|
|
17
|
+
"yaml",
|
|
18
|
+
"secrets",
|
|
19
|
+
"sops",
|
|
20
|
+
"logging",
|
|
21
|
+
"oauth2",
|
|
22
|
+
"oidc",
|
|
23
|
+
"rest-api",
|
|
24
|
+
"http-client",
|
|
25
|
+
"resilience",
|
|
26
|
+
"circuit-breaker",
|
|
27
|
+
"rate-limiter",
|
|
28
|
+
"websocket",
|
|
29
|
+
"alerts",
|
|
30
|
+
"toolkit",
|
|
31
|
+
]
|
|
14
32
|
dynamic = ["version"]
|
|
15
33
|
dependencies = [
|
|
16
34
|
# --- Configuration & Serialization ---
|
|
@@ -43,13 +61,18 @@ dependencies = [
|
|
|
43
61
|
]
|
|
44
62
|
classifiers = [
|
|
45
63
|
"Development Status :: 5 - Production/Stable",
|
|
64
|
+
"Environment :: Console",
|
|
46
65
|
"Intended Audience :: Developers",
|
|
66
|
+
"Operating System :: OS Independent",
|
|
47
67
|
"Programming Language :: Python :: 3",
|
|
48
68
|
"Programming Language :: Python :: 3.10",
|
|
49
69
|
"Programming Language :: Python :: 3.11",
|
|
50
70
|
"Programming Language :: Python :: 3.12",
|
|
51
71
|
"Programming Language :: Python :: 3.13",
|
|
52
72
|
"Programming Language :: Python :: 3.14",
|
|
73
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
74
|
+
"Topic :: System :: Systems Administration",
|
|
75
|
+
"Typing :: Typed",
|
|
53
76
|
]
|
|
54
77
|
|
|
55
78
|
requires-python = ">=3.10"
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
"""List available API endpoints."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Annotated
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
from rich.table import Table
|
|
9
|
+
|
|
10
|
+
from kstlib.cli.common import console
|
|
11
|
+
from kstlib.rapi import load_rapi_config
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from kstlib.rapi.config import ApiConfig, EndpointConfig
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _matches_filter(
|
|
18
|
+
filter_terms: list[str],
|
|
19
|
+
ref: str,
|
|
20
|
+
method: str,
|
|
21
|
+
path: str,
|
|
22
|
+
description: str | None,
|
|
23
|
+
) -> bool:
|
|
24
|
+
"""Check if endpoint matches all filter terms (AND logic).
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
filter_terms: List of lowercase search terms.
|
|
28
|
+
ref: Endpoint reference (e.g., "github.repos").
|
|
29
|
+
method: HTTP method (e.g., "GET").
|
|
30
|
+
path: Endpoint path.
|
|
31
|
+
description: Optional endpoint description.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
True if all terms match any field.
|
|
35
|
+
"""
|
|
36
|
+
searchable = f"{ref} {method} {path} {description or ''}".lower()
|
|
37
|
+
return all(term in searchable for term in filter_terms)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _build_query_body_display(
|
|
41
|
+
ep_config: EndpointConfig,
|
|
42
|
+
method: str,
|
|
43
|
+
) -> tuple[str, str]:
|
|
44
|
+
"""Build query and body column displays.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
ep_config: Endpoint configuration.
|
|
48
|
+
method: HTTP method.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
Tuple of (query_display, body_display).
|
|
52
|
+
"""
|
|
53
|
+
query_display = f"[yellow]{len(ep_config.query)}[/]" if ep_config.query else "-"
|
|
54
|
+
body_display = "-"
|
|
55
|
+
if ep_config.body_template and method in ("POST", "PUT", "PATCH"):
|
|
56
|
+
body_display = f"[green]{len(ep_config.body_template)}[/]"
|
|
57
|
+
return query_display, body_display
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _build_compact_indicator(ep_config: EndpointConfig, method: str) -> str:
|
|
61
|
+
"""Build compact param indicator for non-verbose mode.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
ep_config: Endpoint configuration.
|
|
65
|
+
method: HTTP method.
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
Formatted indicator string (e.g., " (4) (2)").
|
|
69
|
+
"""
|
|
70
|
+
indicator = ""
|
|
71
|
+
if ep_config.query:
|
|
72
|
+
indicator += f" [yellow]({len(ep_config.query)})[/]"
|
|
73
|
+
if ep_config.body_template and method in ("POST", "PUT", "PATCH"):
|
|
74
|
+
indicator += f" [green]({len(ep_config.body_template)})[/]"
|
|
75
|
+
return indicator
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _add_endpoint_row(
|
|
79
|
+
table: Table,
|
|
80
|
+
ep_config: EndpointConfig,
|
|
81
|
+
api_name: str,
|
|
82
|
+
verbose: bool,
|
|
83
|
+
*,
|
|
84
|
+
short_desc: bool = False,
|
|
85
|
+
) -> None:
|
|
86
|
+
"""Add a single endpoint row to the table.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
table: Rich table to add row to.
|
|
90
|
+
ep_config: Endpoint configuration.
|
|
91
|
+
api_name: Parent API name.
|
|
92
|
+
verbose: Whether to show verbose columns.
|
|
93
|
+
short_desc: Whether to truncate description (verbose mode only).
|
|
94
|
+
"""
|
|
95
|
+
ref = f"{api_name}.{ep_config.name}"
|
|
96
|
+
method = ep_config.method.upper()
|
|
97
|
+
path_display = f"[dim]{ep_config.path}[/]"
|
|
98
|
+
|
|
99
|
+
if verbose:
|
|
100
|
+
query_display, body_display = _build_query_body_display(ep_config, method)
|
|
101
|
+
description = ep_config.description or ""
|
|
102
|
+
desc_display = (description[:40] + "...") if short_desc and len(description) > 43 else description
|
|
103
|
+
table.add_row(ref, method, path_display, query_display, body_display, desc_display)
|
|
104
|
+
else:
|
|
105
|
+
indicator = _build_compact_indicator(ep_config, method)
|
|
106
|
+
table.add_row(ref, method, path_display + indicator)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _create_table(verbose: bool) -> Table:
|
|
110
|
+
"""Create the endpoints table with appropriate columns.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
verbose: Whether to include verbose columns.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
Configured Rich table.
|
|
117
|
+
"""
|
|
118
|
+
table = Table(title="Available Endpoints", show_lines=False)
|
|
119
|
+
table.add_column("Reference", style="cyan")
|
|
120
|
+
table.add_column("Method", style="green", justify="center")
|
|
121
|
+
table.add_column("Path")
|
|
122
|
+
|
|
123
|
+
if verbose:
|
|
124
|
+
table.add_column("Query", justify="center")
|
|
125
|
+
table.add_column("Body", justify="center")
|
|
126
|
+
table.add_column("Description", style="dim")
|
|
127
|
+
|
|
128
|
+
return table
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _collect_matching_endpoints(
|
|
132
|
+
apis: dict[str, ApiConfig],
|
|
133
|
+
filter_terms: list[str],
|
|
134
|
+
) -> list[tuple[str, EndpointConfig]]:
|
|
135
|
+
"""Collect endpoints matching the filter.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
apis: Dictionary of API configurations.
|
|
139
|
+
filter_terms: List of lowercase filter terms.
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
List of (api_name, endpoint_config) tuples.
|
|
143
|
+
"""
|
|
144
|
+
results = []
|
|
145
|
+
for api_name, api_config in sorted(apis.items()):
|
|
146
|
+
for ep_name, ep_config in sorted(api_config.endpoints.items()):
|
|
147
|
+
ref = f"{api_name}.{ep_name}"
|
|
148
|
+
method = ep_config.method.upper()
|
|
149
|
+
description = ep_config.description or ""
|
|
150
|
+
|
|
151
|
+
if filter_terms and not _matches_filter(filter_terms, ref, method, ep_config.path, description):
|
|
152
|
+
continue
|
|
153
|
+
|
|
154
|
+
results.append((api_name, ep_config))
|
|
155
|
+
return results
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def list_endpoints(
|
|
159
|
+
api: Annotated[
|
|
160
|
+
str | None,
|
|
161
|
+
typer.Argument(help="Filter by API name (optional)."),
|
|
162
|
+
] = None,
|
|
163
|
+
verbose: Annotated[
|
|
164
|
+
bool,
|
|
165
|
+
typer.Option(
|
|
166
|
+
"--verbose",
|
|
167
|
+
"-v",
|
|
168
|
+
help="Show additional details (method, description, query params).",
|
|
169
|
+
),
|
|
170
|
+
] = False,
|
|
171
|
+
filter_str: Annotated[
|
|
172
|
+
str | None,
|
|
173
|
+
typer.Option(
|
|
174
|
+
"--filter",
|
|
175
|
+
"-f",
|
|
176
|
+
help="Filter endpoints by keyword(s). Searches in ref, method, path, description.",
|
|
177
|
+
),
|
|
178
|
+
] = None,
|
|
179
|
+
short_desc: Annotated[
|
|
180
|
+
bool,
|
|
181
|
+
typer.Option(
|
|
182
|
+
"--short-desc",
|
|
183
|
+
help="Truncate descriptions to 40 chars (verbose mode only).",
|
|
184
|
+
),
|
|
185
|
+
] = False,
|
|
186
|
+
) -> None:
|
|
187
|
+
"""List all configured API endpoints.
|
|
188
|
+
|
|
189
|
+
Examples:
|
|
190
|
+
# List all endpoints
|
|
191
|
+
kstlib rapi list
|
|
192
|
+
|
|
193
|
+
# List endpoints for specific API
|
|
194
|
+
kstlib rapi list github
|
|
195
|
+
|
|
196
|
+
# Filter by keyword (searches everywhere)
|
|
197
|
+
kstlib rapi list --filter "delete"
|
|
198
|
+
|
|
199
|
+
# Multiple keywords (AND logic)
|
|
200
|
+
kstlib rapi list --filter "annotation GET"
|
|
201
|
+
|
|
202
|
+
# Combine API filter with keyword filter
|
|
203
|
+
kstlib rapi list annotations --filter "member"
|
|
204
|
+
|
|
205
|
+
# Verbose output with method, description, query params
|
|
206
|
+
kstlib rapi list -v
|
|
207
|
+
|
|
208
|
+
# Show details for specific endpoint (use 'rapi show')
|
|
209
|
+
kstlib rapi show annotations.create
|
|
210
|
+
"""
|
|
211
|
+
try:
|
|
212
|
+
config_manager = load_rapi_config()
|
|
213
|
+
except Exception as e: # pylint: disable=broad-exception-caught
|
|
214
|
+
console.print(f"[red]Failed to load rapi config: {e}[/]")
|
|
215
|
+
raise typer.Exit(code=1) from e
|
|
216
|
+
|
|
217
|
+
apis = config_manager.apis
|
|
218
|
+
|
|
219
|
+
if not apis:
|
|
220
|
+
console.print("[yellow]No APIs configured in kstlib.conf.yml[/]")
|
|
221
|
+
console.print("[dim]Add APIs under 'rapi.api' section.[/]")
|
|
222
|
+
raise typer.Exit(code=0)
|
|
223
|
+
|
|
224
|
+
# Filter by API name if specified
|
|
225
|
+
if api:
|
|
226
|
+
if api not in apis:
|
|
227
|
+
console.print(f"[red]API '{api}' not found.[/]")
|
|
228
|
+
console.print(f"[dim]Available APIs: {', '.join(apis.keys())}[/]")
|
|
229
|
+
raise typer.Exit(code=1)
|
|
230
|
+
apis = {api: apis[api]}
|
|
231
|
+
|
|
232
|
+
# Parse filter terms
|
|
233
|
+
filter_terms = filter_str.lower().split() if filter_str else []
|
|
234
|
+
|
|
235
|
+
# Collect matching endpoints
|
|
236
|
+
matches = _collect_matching_endpoints(apis, filter_terms)
|
|
237
|
+
|
|
238
|
+
if not matches:
|
|
239
|
+
if filter_terms:
|
|
240
|
+
console.print(f"[yellow]No endpoints matching '{filter_str}'[/]")
|
|
241
|
+
else:
|
|
242
|
+
console.print("[yellow]No endpoints found.[/]")
|
|
243
|
+
raise typer.Exit(code=0)
|
|
244
|
+
|
|
245
|
+
# Build and populate table
|
|
246
|
+
table = _create_table(verbose)
|
|
247
|
+
for api_name, ep_config in matches:
|
|
248
|
+
_add_endpoint_row(table, ep_config, api_name, verbose, short_desc=short_desc)
|
|
249
|
+
|
|
250
|
+
console.print(table)
|
|
251
|
+
|
|
252
|
+
# Summary
|
|
253
|
+
total_apis = len(apis)
|
|
254
|
+
total_endpoints = sum(len(a.endpoints) for a in apis.values())
|
|
255
|
+
if filter_terms:
|
|
256
|
+
console.print(f"\n[dim]{len(matches)} matching / {total_endpoints} total endpoints[/]")
|
|
257
|
+
else:
|
|
258
|
+
console.print(f"\n[dim]{total_endpoints} endpoints across {total_apis} API(s)[/]")
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
__all__ = ["list_endpoints"]
|
|
@@ -623,6 +623,17 @@ rapi:
|
|
|
623
623
|
retry_delay: 1.0 # Initial delay between retries (seconds)
|
|
624
624
|
retry_backoff: 2.0 # Exponential backoff multiplier
|
|
625
625
|
|
|
626
|
+
# Safeguard configuration for dangerous HTTP methods
|
|
627
|
+
# Endpoints using these methods MUST define a safeguard string
|
|
628
|
+
# to prevent accidental destructive operations
|
|
629
|
+
safeguard:
|
|
630
|
+
# HTTP methods that require a safeguard to be defined on endpoints
|
|
631
|
+
# Default: DELETE and PUT (most destructive operations)
|
|
632
|
+
# Set to empty list [] to disable safeguard requirements
|
|
633
|
+
required_methods:
|
|
634
|
+
- DELETE
|
|
635
|
+
- PUT
|
|
636
|
+
|
|
626
637
|
# Pretty-print settings for CLI output
|
|
627
638
|
# Controls formatting of JSON and XML responses in terminal
|
|
628
639
|
pretty_render:
|
|
@@ -85,26 +85,32 @@ from kstlib.rapi.config import (
|
|
|
85
85
|
EndpointConfig,
|
|
86
86
|
HmacConfig,
|
|
87
87
|
RapiConfigManager,
|
|
88
|
+
SafeguardConfig,
|
|
88
89
|
load_rapi_config,
|
|
89
90
|
)
|
|
90
91
|
from kstlib.rapi.credentials import CredentialRecord, CredentialResolver
|
|
91
92
|
from kstlib.rapi.exceptions import (
|
|
93
|
+
ConfirmationRequiredError,
|
|
92
94
|
CredentialError,
|
|
93
95
|
EndpointAmbiguousError,
|
|
94
96
|
EndpointNotFoundError,
|
|
97
|
+
EnvVarError,
|
|
95
98
|
RapiError,
|
|
96
99
|
RequestError,
|
|
97
100
|
ResponseTooLargeError,
|
|
101
|
+
SafeguardMissingError,
|
|
98
102
|
)
|
|
99
103
|
|
|
100
104
|
__all__ = [
|
|
101
105
|
"ApiConfig",
|
|
106
|
+
"ConfirmationRequiredError",
|
|
102
107
|
"CredentialError",
|
|
103
108
|
"CredentialRecord",
|
|
104
109
|
"CredentialResolver",
|
|
105
110
|
"EndpointAmbiguousError",
|
|
106
111
|
"EndpointConfig",
|
|
107
112
|
"EndpointNotFoundError",
|
|
113
|
+
"EnvVarError",
|
|
108
114
|
"HmacConfig",
|
|
109
115
|
"RapiClient",
|
|
110
116
|
"RapiConfigManager",
|
|
@@ -112,6 +118,8 @@ __all__ = [
|
|
|
112
118
|
"RapiResponse",
|
|
113
119
|
"RequestError",
|
|
114
120
|
"ResponseTooLargeError",
|
|
121
|
+
"SafeguardConfig",
|
|
122
|
+
"SafeguardMissingError",
|
|
115
123
|
"call",
|
|
116
124
|
"call_async",
|
|
117
125
|
"load_rapi_config",
|
|
@@ -27,6 +27,7 @@ from kstlib.rapi.config import (
|
|
|
27
27
|
)
|
|
28
28
|
from kstlib.rapi.credentials import CredentialRecord, CredentialResolver
|
|
29
29
|
from kstlib.rapi.exceptions import (
|
|
30
|
+
ConfirmationRequiredError,
|
|
30
31
|
RequestError,
|
|
31
32
|
ResponseTooLargeError,
|
|
32
33
|
)
|
|
@@ -45,6 +46,37 @@ def _log_trace(msg: str, *args: Any) -> None:
|
|
|
45
46
|
log.log(TRACE_LEVEL, msg, *args)
|
|
46
47
|
|
|
47
48
|
|
|
49
|
+
def _validate_safeguard(
|
|
50
|
+
endpoint_config: EndpointConfig,
|
|
51
|
+
args: tuple[Any, ...],
|
|
52
|
+
kwargs: dict[str, Any],
|
|
53
|
+
confirm: str | None,
|
|
54
|
+
) -> None:
|
|
55
|
+
"""Validate safeguard confirmation for dangerous endpoints.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
endpoint_config: Endpoint configuration.
|
|
59
|
+
args: Positional arguments for path/safeguard substitution.
|
|
60
|
+
kwargs: Keyword arguments for path/safeguard substitution.
|
|
61
|
+
confirm: Confirmation string provided by caller.
|
|
62
|
+
|
|
63
|
+
Raises:
|
|
64
|
+
ConfirmationRequiredError: If safeguard is required but confirm is missing or wrong.
|
|
65
|
+
"""
|
|
66
|
+
if endpoint_config.safeguard is None:
|
|
67
|
+
return
|
|
68
|
+
|
|
69
|
+
expected = endpoint_config.build_safeguard(*args, **kwargs)
|
|
70
|
+
if expected is None:
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
if confirm is None:
|
|
74
|
+
raise ConfirmationRequiredError(endpoint_config.full_ref, expected=expected)
|
|
75
|
+
|
|
76
|
+
if confirm != expected:
|
|
77
|
+
raise ConfirmationRequiredError(endpoint_config.full_ref, expected=expected, actual=confirm)
|
|
78
|
+
|
|
79
|
+
|
|
48
80
|
@dataclass
|
|
49
81
|
class RapiResponse:
|
|
50
82
|
"""Response from an API call.
|
|
@@ -238,6 +270,7 @@ class RapiClient:
|
|
|
238
270
|
body: Any = None,
|
|
239
271
|
headers: Mapping[str, str] | None = None,
|
|
240
272
|
timeout: float | None = None,
|
|
273
|
+
confirm: str | None = None,
|
|
241
274
|
**kwargs: Any,
|
|
242
275
|
) -> RapiResponse:
|
|
243
276
|
"""Make a synchronous API call.
|
|
@@ -248,12 +281,14 @@ class RapiClient:
|
|
|
248
281
|
body: Request body (dict for JSON, str for raw).
|
|
249
282
|
headers: Runtime headers (override service/endpoint headers).
|
|
250
283
|
timeout: Request timeout (uses config default if None).
|
|
284
|
+
confirm: Confirmation string for dangerous endpoints with safeguard.
|
|
251
285
|
**kwargs: Keyword arguments for path parameters and query params.
|
|
252
286
|
|
|
253
287
|
Returns:
|
|
254
288
|
RapiResponse with parsed data.
|
|
255
289
|
|
|
256
290
|
Raises:
|
|
291
|
+
ConfirmationRequiredError: If safeguard requires confirmation.
|
|
257
292
|
RequestError: If request fails after retries.
|
|
258
293
|
ResponseTooLargeError: If response exceeds max size.
|
|
259
294
|
|
|
@@ -262,6 +297,7 @@ class RapiClient:
|
|
|
262
297
|
>>> client.call("httpbin.get_ip") # doctest: +SKIP
|
|
263
298
|
>>> client.call("httpbin.delayed", 5) # doctest: +SKIP
|
|
264
299
|
>>> client.call("httpbin.post_data", body={"key": "value"}) # doctest: +SKIP
|
|
300
|
+
>>> client.call("admin.delete_user", userId="123", confirm="DELETE USER 123") # doctest: +SKIP
|
|
265
301
|
"""
|
|
266
302
|
log.debug("Calling endpoint: %s", endpoint_ref)
|
|
267
303
|
|
|
@@ -269,6 +305,9 @@ class RapiClient:
|
|
|
269
305
|
api_config, endpoint_config = self._config_manager.resolve(endpoint_ref)
|
|
270
306
|
_log_trace("Resolved to: %s", endpoint_config.full_ref)
|
|
271
307
|
|
|
308
|
+
# Validate safeguard before proceeding
|
|
309
|
+
_validate_safeguard(endpoint_config, args, kwargs, confirm)
|
|
310
|
+
|
|
272
311
|
# Build request
|
|
273
312
|
request = self._build_request(
|
|
274
313
|
api_config,
|
|
@@ -290,6 +329,7 @@ class RapiClient:
|
|
|
290
329
|
body: Any = None,
|
|
291
330
|
headers: Mapping[str, str] | None = None,
|
|
292
331
|
timeout: float | None = None,
|
|
332
|
+
confirm: str | None = None,
|
|
293
333
|
**kwargs: Any,
|
|
294
334
|
) -> RapiResponse:
|
|
295
335
|
"""Make an asynchronous API call.
|
|
@@ -300,12 +340,14 @@ class RapiClient:
|
|
|
300
340
|
body: Request body (dict for JSON, str for raw).
|
|
301
341
|
headers: Runtime headers (override service/endpoint headers).
|
|
302
342
|
timeout: Request timeout (uses config default if None).
|
|
343
|
+
confirm: Confirmation string for dangerous endpoints with safeguard.
|
|
303
344
|
**kwargs: Keyword arguments for path parameters and query params.
|
|
304
345
|
|
|
305
346
|
Returns:
|
|
306
347
|
RapiResponse with parsed data.
|
|
307
348
|
|
|
308
349
|
Raises:
|
|
350
|
+
ConfirmationRequiredError: If safeguard requires confirmation.
|
|
309
351
|
RequestError: If request fails after retries.
|
|
310
352
|
ResponseTooLargeError: If response exceeds max size.
|
|
311
353
|
"""
|
|
@@ -315,6 +357,9 @@ class RapiClient:
|
|
|
315
357
|
api_config, endpoint_config = self._config_manager.resolve(endpoint_ref)
|
|
316
358
|
_log_trace("Resolved to: %s", endpoint_config.full_ref)
|
|
317
359
|
|
|
360
|
+
# Validate safeguard before proceeding
|
|
361
|
+
_validate_safeguard(endpoint_config, args, kwargs, confirm)
|
|
362
|
+
|
|
318
363
|
# Build request
|
|
319
364
|
request = self._build_request(
|
|
320
365
|
api_config,
|
|
@@ -814,6 +859,7 @@ def call(
|
|
|
814
859
|
*args: Any,
|
|
815
860
|
body: Any = None,
|
|
816
861
|
headers: Mapping[str, str] | None = None,
|
|
862
|
+
confirm: str | None = None,
|
|
817
863
|
**kwargs: Any,
|
|
818
864
|
) -> RapiResponse:
|
|
819
865
|
"""Convenience function for quick API calls.
|
|
@@ -825,6 +871,7 @@ def call(
|
|
|
825
871
|
*args: Positional path parameters.
|
|
826
872
|
body: Request body.
|
|
827
873
|
headers: Runtime headers.
|
|
874
|
+
confirm: Confirmation string for dangerous endpoints with safeguard.
|
|
828
875
|
**kwargs: Keyword parameters.
|
|
829
876
|
|
|
830
877
|
Returns:
|
|
@@ -835,7 +882,7 @@ def call(
|
|
|
835
882
|
>>> response = call("httpbin.get_ip") # doctest: +SKIP
|
|
836
883
|
"""
|
|
837
884
|
client = RapiClient()
|
|
838
|
-
return client.call(endpoint_ref, *args, body=body, headers=headers, **kwargs)
|
|
885
|
+
return client.call(endpoint_ref, *args, body=body, headers=headers, confirm=confirm, **kwargs)
|
|
839
886
|
|
|
840
887
|
|
|
841
888
|
async def call_async(
|
|
@@ -843,6 +890,7 @@ async def call_async(
|
|
|
843
890
|
*args: Any,
|
|
844
891
|
body: Any = None,
|
|
845
892
|
headers: Mapping[str, str] | None = None,
|
|
893
|
+
confirm: str | None = None,
|
|
846
894
|
**kwargs: Any,
|
|
847
895
|
) -> RapiResponse:
|
|
848
896
|
"""Convenience function for async API calls.
|
|
@@ -854,6 +902,7 @@ async def call_async(
|
|
|
854
902
|
*args: Positional path parameters.
|
|
855
903
|
body: Request body.
|
|
856
904
|
headers: Runtime headers.
|
|
905
|
+
confirm: Confirmation string for dangerous endpoints with safeguard.
|
|
857
906
|
**kwargs: Keyword parameters.
|
|
858
907
|
|
|
859
908
|
Returns:
|
|
@@ -864,7 +913,7 @@ async def call_async(
|
|
|
864
913
|
>>> response = await call_async("httpbin.get_ip") # doctest: +SKIP
|
|
865
914
|
"""
|
|
866
915
|
client = RapiClient()
|
|
867
|
-
return await client.call_async(endpoint_ref, *args, body=body, headers=headers, **kwargs)
|
|
916
|
+
return await client.call_async(endpoint_ref, *args, body=body, headers=headers, confirm=confirm, **kwargs)
|
|
868
917
|
|
|
869
918
|
|
|
870
919
|
__all__ = [
|