arize-phoenix 8.30.0__py3-none-any.whl → 8.32.0__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.
Potentially problematic release.
This version of arize-phoenix might be problematic. Click here for more details.
- {arize_phoenix-8.30.0.dist-info → arize_phoenix-8.32.0.dist-info}/METADATA +2 -1
- {arize_phoenix-8.30.0.dist-info → arize_phoenix-8.32.0.dist-info}/RECORD +14 -13
- phoenix/db/engines.py +14 -21
- phoenix/db/pg_config.py +197 -0
- phoenix/server/static/.vite/manifest.json +9 -9
- phoenix/server/static/assets/{components-BypB0fGT.js → components-x-gKFJ8C.js} +199 -188
- phoenix/server/static/assets/{index-Ccebc6-h.js → index-B0CbpsxD.js} +2 -2
- phoenix/server/static/assets/{pages-DGdjQlsy.js → pages-BU4VdyeH.js} +346 -346
- phoenix/trace/fixtures.py +24 -0
- phoenix/version.py +1 -1
- {arize_phoenix-8.30.0.dist-info → arize_phoenix-8.32.0.dist-info}/WHEEL +0 -0
- {arize_phoenix-8.30.0.dist-info → arize_phoenix-8.32.0.dist-info}/entry_points.txt +0 -0
- {arize_phoenix-8.30.0.dist-info → arize_phoenix-8.32.0.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-8.30.0.dist-info → arize_phoenix-8.32.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: arize-phoenix
|
|
3
|
-
Version: 8.
|
|
3
|
+
Version: 8.32.0
|
|
4
4
|
Summary: AI Observability and Evaluation
|
|
5
5
|
Project-URL: Documentation, https://docs.arize.com/phoenix/
|
|
6
6
|
Project-URL: Issues, https://github.com/Arize-ai/phoenix/issues
|
|
@@ -248,6 +248,7 @@ Join our community to connect with thousands of AI builders.
|
|
|
248
248
|
- 🐞 Report bugs with [GitHub Issues](https://github.com/Arize-ai/phoenix/issues).
|
|
249
249
|
- 𝕏 Follow us on [𝕏](https://twitter.com/ArizePhoenix).
|
|
250
250
|
- 🗺️ Check out our [roadmap](https://github.com/orgs/Arize-ai/projects/45) to see where we're heading next.
|
|
251
|
+
- 🧑🏫 Deep dive into everything [Agents](http://arize.com/ai-agents/) and [LLM Evaluations](https://arize.com/llm-evaluation) on Arize's Learning Hubs.
|
|
251
252
|
|
|
252
253
|
## Breaking Changes
|
|
253
254
|
|
|
@@ -6,7 +6,7 @@ phoenix/exceptions.py,sha256=n2L2KKuecrdflB9MsCdAYCiSEvGJptIsfRkXMoJle7A,169
|
|
|
6
6
|
phoenix/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
7
7
|
phoenix/services.py,sha256=ngkyKGVatX3cO2WJdo2hKdaVKP-xJCMvqthvga6kJss,5196
|
|
8
8
|
phoenix/settings.py,sha256=x87BX7hWGQQZbrW_vrYqFR_izCGfO9gFc--JXUG4Tdk,754
|
|
9
|
-
phoenix/version.py,sha256=
|
|
9
|
+
phoenix/version.py,sha256=CPcjvGHbAOwrtXWXWvvKo1NJoSarXEuhf5QxQmrv1Do,23
|
|
10
10
|
phoenix/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
phoenix/core/embedding_dimension.py,sha256=zKGbcvwOXgLf-yrJBpQyKtd-LEOPRKHnUToyAU8Owis,87
|
|
12
12
|
phoenix/core/model.py,sha256=qBFraOtmwCCnWJltKNP18DDG0mULXigytlFsa6YOz6k,4837
|
|
@@ -16,12 +16,13 @@ phoenix/db/README.md,sha256=7BFJuecWJjFSxEYmoSv4CvoFHHszX4tFy3HJExOxS-4,8661
|
|
|
16
16
|
phoenix/db/__init__.py,sha256=pDjEFXukHmJBM-1D8RjmXkvLsz85YWNxMQczt81ec3A,118
|
|
17
17
|
phoenix/db/alembic.ini,sha256=GIS6HpHaKaJbbuahZg1Rc1D2_QqyCkV9r58wdARGf6w,3262
|
|
18
18
|
phoenix/db/bulk_inserter.py,sha256=faNjuwLqqsw4ky8sa4D0h9u5TvEDTOjrccUW89L008E,12725
|
|
19
|
-
phoenix/db/engines.py,sha256=
|
|
19
|
+
phoenix/db/engines.py,sha256=tB_8iWMDz0folryVvw29sbBUxJOB2XZ-Xx0Uexj3uns,6889
|
|
20
20
|
phoenix/db/enums.py,sha256=tt7iovXLhVTLZ3_LbHNGgcI44SnNjXfkKtLAZG57T54,428
|
|
21
21
|
phoenix/db/facilitator.py,sha256=6CeUMNTkNXrdviSQspY9ktFpVX-JHXcMJz6L0PuHxrI,7481
|
|
22
22
|
phoenix/db/helpers.py,sha256=rbbHcl-STzcEpcXCYx6jbKzko7r3ggrWHHsXjZ48HsM,5352
|
|
23
23
|
phoenix/db/migrate.py,sha256=oUrXH8yEbcpL4eh09aSCuUiSrhFli0eT5D_j4ZmYChY,2797
|
|
24
24
|
phoenix/db/models.py,sha256=TbHgtT7WWdkQK-OtLsUqp3MwP23HGV1IaSAWTqCf5ac,45707
|
|
25
|
+
phoenix/db/pg_config.py,sha256=h6mB7qF7t4Zk6VGvAiyefHGVu74o-yJynaWzeE39k9Y,6001
|
|
25
26
|
phoenix/db/insertion/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
27
|
phoenix/db/insertion/constants.py,sha256=8wifm7X-1XvroZ__R2Gc96NsgLhTDn0zXl4lehlXtcA,70
|
|
27
28
|
phoenix/db/insertion/dataset.py,sha256=I9OC1ouVx7m6BH_c8hvcxW1dWGRAtpvXee29yBTuFkg,7136
|
|
@@ -319,10 +320,10 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
|
|
|
319
320
|
phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
|
|
320
321
|
phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
|
|
321
322
|
phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
|
|
322
|
-
phoenix/server/static/.vite/manifest.json,sha256=
|
|
323
|
-
phoenix/server/static/assets/components-
|
|
324
|
-
phoenix/server/static/assets/index-
|
|
325
|
-
phoenix/server/static/assets/pages-
|
|
323
|
+
phoenix/server/static/.vite/manifest.json,sha256=lkhQOaQx8cjiJQeVrrDfp2_pSvKAS8o-DDrzjdLXY7Y,2165
|
|
324
|
+
phoenix/server/static/assets/components-x-gKFJ8C.js,sha256=X4qsvxt0Au4bURJd_ntsb_5zDbCCf6ExCyWjTc3QANc,458101
|
|
325
|
+
phoenix/server/static/assets/index-B0CbpsxD.js,sha256=0Y1a5THRDD7MIVBniyp-LQRcFniB0L6GuLI7LIorVNo,60460
|
|
326
|
+
phoenix/server/static/assets/pages-BU4VdyeH.js,sha256=7rSqUn1XhMhJJdw8u6lEcvwWGpVJI0ciX1y3Z5euwF0,866121
|
|
326
327
|
phoenix/server/static/assets/vendor-BfhM_F1u.js,sha256=S90L1KRZOw_NX6C9FENfLs6bSuEzf7zVDAqjZAZJZgE,2514280
|
|
327
328
|
phoenix/server/static/assets/vendor-Cg6lcjUC.css,sha256=nZrkr0u6NNElFGvpWHk9GTHeGoibCXCli1bE7mXZGZg,1816
|
|
328
329
|
phoenix/server/static/assets/vendor-arizeai-CxXYQNUl.js,sha256=V0umBNhH2psKhzwNKvLylYrqVfHu4I6NDSqejmR2OIU,193248
|
|
@@ -342,7 +343,7 @@ phoenix/trace/attributes.py,sha256=hyEKYZWPCP4NRmW7VmiC2voa3TH7FYKUBR9DYiVfXlw,1
|
|
|
342
343
|
phoenix/trace/errors.py,sha256=wB1z8qdPckngdfU-TORToekvg3344oNFAA83_hC2yFY,180
|
|
343
344
|
phoenix/trace/evaluation_conventions.py,sha256=t8jydM3U0-T5YpiQKRJ3tWdWGlHtzKyttYdw-ddvPOk,1048
|
|
344
345
|
phoenix/trace/exporter.py,sha256=bUXh8fjJIbHurrnt4bAm-cCWqUN5FqNsIc8DZzzklkQ,4695
|
|
345
|
-
phoenix/trace/fixtures.py,sha256=
|
|
346
|
+
phoenix/trace/fixtures.py,sha256=1c7fsyvmxC53Fib9T_Qxp_Ly3OZdDbkLQ0XpFzikEjk,20298
|
|
346
347
|
phoenix/trace/otel.py,sha256=RJSbAuzS4KBS0t-fntXQaaYwv7FmIXRMrw65DI67z8k,10622
|
|
347
348
|
phoenix/trace/projects.py,sha256=9dKv1aiKL4IYMFsg2xnC6EOIRO0YHtkR5o9ALHbMK9g,2178
|
|
348
349
|
phoenix/trace/schemas.py,sha256=Su6e567Bei9oo6PsWO2srTcPAj9C2bMgbGtx64Sgqeg,6332
|
|
@@ -369,9 +370,9 @@ phoenix/utilities/project.py,sha256=auVpARXkDb-JgeX5f2aStyFIkeKvGwN9l7qrFeJMVxI,
|
|
|
369
370
|
phoenix/utilities/re.py,sha256=6YyUWIkv0zc2SigsxfOWIHzdpjKA_TZo2iqKq7zJKvw,2081
|
|
370
371
|
phoenix/utilities/span_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
371
372
|
phoenix/utilities/template_formatters.py,sha256=gh9PJD6WEGw7TEYXfSst1UR4pWWwmjxMLrDVQ_CkpkQ,2779
|
|
372
|
-
arize_phoenix-8.
|
|
373
|
-
arize_phoenix-8.
|
|
374
|
-
arize_phoenix-8.
|
|
375
|
-
arize_phoenix-8.
|
|
376
|
-
arize_phoenix-8.
|
|
377
|
-
arize_phoenix-8.
|
|
373
|
+
arize_phoenix-8.32.0.dist-info/METADATA,sha256=3kMwFbV8oWeYk1Y3oehODTSdyHZAWNyYiSq6vgSsWPg,24638
|
|
374
|
+
arize_phoenix-8.32.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
375
|
+
arize_phoenix-8.32.0.dist-info/entry_points.txt,sha256=Pgpn8Upxx9P8z8joPXZWl2LlnAlGc3gcQoVchb06X1Q,94
|
|
376
|
+
arize_phoenix-8.32.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
|
|
377
|
+
arize_phoenix-8.32.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
|
|
378
|
+
arize_phoenix-8.32.0.dist-info/RECORD,,
|
phoenix/db/engines.py
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import asyncio
|
|
2
4
|
import json
|
|
5
|
+
import logging
|
|
3
6
|
from collections.abc import Callable
|
|
4
7
|
from datetime import datetime
|
|
5
8
|
from enum import Enum
|
|
6
9
|
from sqlite3 import Connection
|
|
7
|
-
from typing import Any
|
|
10
|
+
from typing import Any
|
|
8
11
|
|
|
9
12
|
import aiosqlite
|
|
10
13
|
import numpy as np
|
|
@@ -18,10 +21,13 @@ from phoenix.config import LoggingMode, get_env_database_schema
|
|
|
18
21
|
from phoenix.db.helpers import SupportedSQLDialect
|
|
19
22
|
from phoenix.db.migrate import migrate_in_thread
|
|
20
23
|
from phoenix.db.models import init_models
|
|
24
|
+
from phoenix.db.pg_config import get_pg_config
|
|
21
25
|
from phoenix.settings import Settings
|
|
22
26
|
|
|
23
27
|
sqlean.extensions.enable("text", "stats")
|
|
24
28
|
|
|
29
|
+
logger = logging.getLogger(__name__)
|
|
30
|
+
|
|
25
31
|
|
|
26
32
|
def set_sqlite_pragma(connection: Connection, _: Any) -> None:
|
|
27
33
|
cursor = connection.cursor()
|
|
@@ -163,15 +169,20 @@ def aio_postgresql_engine(
|
|
|
163
169
|
log_to_stdout: bool = False,
|
|
164
170
|
log_migrations_to_stdout: bool = True,
|
|
165
171
|
) -> AsyncEngine:
|
|
172
|
+
asyncpg_url, asyncpg_args = get_pg_config(url, "asyncpg")
|
|
166
173
|
engine = create_async_engine(
|
|
167
|
-
url=
|
|
174
|
+
url=asyncpg_url,
|
|
175
|
+
connect_args=asyncpg_args,
|
|
168
176
|
echo=log_to_stdout,
|
|
169
177
|
json_serializer=_dumps,
|
|
170
178
|
)
|
|
171
179
|
if not migrate:
|
|
172
180
|
return engine
|
|
181
|
+
|
|
182
|
+
psycopg_url, psycopg_args = get_pg_config(url, "psycopg")
|
|
173
183
|
sync_engine = sqlalchemy.create_engine(
|
|
174
|
-
url=
|
|
184
|
+
url=psycopg_url,
|
|
185
|
+
connect_args=psycopg_args,
|
|
175
186
|
echo=log_migrations_to_stdout,
|
|
176
187
|
json_serializer=_dumps,
|
|
177
188
|
)
|
|
@@ -181,24 +192,6 @@ def aio_postgresql_engine(
|
|
|
181
192
|
return engine
|
|
182
193
|
|
|
183
194
|
|
|
184
|
-
def _asyncpg_url_query(query: Mapping[str, Any]) -> dict[str, Any]:
|
|
185
|
-
ans = dict(query)
|
|
186
|
-
if sslmode := (ans.pop("sslmode", None) or ans.pop("ssl", None)):
|
|
187
|
-
# https://github.com/MagicStack/asyncpg/issues/737
|
|
188
|
-
ans["ssl"] = sslmode
|
|
189
|
-
return ans
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
def _psycopg_url_query(query: Mapping[str, Any]) -> dict[str, Any]:
|
|
193
|
-
ans = dict(query)
|
|
194
|
-
if sslmode := (ans.pop("sslmode", None) or ans.pop("ssl", None)):
|
|
195
|
-
ans["sslmode"] = sslmode
|
|
196
|
-
# prepared_statement_cache_size is only used by asyncpg, see:
|
|
197
|
-
# https://docs.sqlalchemy.org/en/20/dialects/postgresql.html#prepared-statement-cache
|
|
198
|
-
ans.pop("prepared_statement_cache_size", None)
|
|
199
|
-
return ans
|
|
200
|
-
|
|
201
|
-
|
|
202
195
|
def _dumps(obj: Any) -> str:
|
|
203
196
|
return json.dumps(obj, cls=_Encoder)
|
|
204
197
|
|
phoenix/db/pg_config.py
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import ssl
|
|
4
|
+
from typing import Any, Container, Final, Literal, Mapping, TypedDict, get_type_hints
|
|
5
|
+
|
|
6
|
+
from sqlalchemy import URL
|
|
7
|
+
from typing_extensions import assert_never
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_pg_config(
|
|
11
|
+
url: URL,
|
|
12
|
+
driver: Literal["psycopg", "asyncpg"],
|
|
13
|
+
) -> tuple[URL, dict[str, Any]]:
|
|
14
|
+
"""Convert SQLAlchemy URL to driver-specific configuration.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
url: SQLAlchemy URL
|
|
18
|
+
driver: "psycopg" or "asyncpg"
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
Tuple of (base_url, connect_args):
|
|
22
|
+
- base_url: URL with driver prefix and non-SSL parameters
|
|
23
|
+
- connect_args: SSL configuration for the driver
|
|
24
|
+
"""
|
|
25
|
+
# Create new URL with appropriate driver
|
|
26
|
+
query = url.query
|
|
27
|
+
ssl_args = _get_ssl_args(query)
|
|
28
|
+
|
|
29
|
+
# Create base URL without SSL parameters
|
|
30
|
+
base_url = url.set(
|
|
31
|
+
drivername=f"postgresql+{driver}",
|
|
32
|
+
query={k: v for k, v in query.items() if k not in _SSL_KEYS},
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
# Get appropriate SSL configuration based on driver
|
|
36
|
+
if driver == "psycopg":
|
|
37
|
+
connect_args = dict(ssl_args)
|
|
38
|
+
# Remove asyncpg-specific parameters from base URL
|
|
39
|
+
base_url = base_url.set(query=_remove_asyncpg_only_params(base_url.query))
|
|
40
|
+
elif driver == "asyncpg":
|
|
41
|
+
# Only create SSL context if we have SSL parameters and sslmode is not disable
|
|
42
|
+
if ssl_args and ssl_args.get("sslmode") != "disable":
|
|
43
|
+
connect_args = {"ssl": _get_ssl_context(ssl_args)}
|
|
44
|
+
else:
|
|
45
|
+
connect_args = {}
|
|
46
|
+
else:
|
|
47
|
+
assert_never(driver)
|
|
48
|
+
return base_url, connect_args
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class _SSLArgs(TypedDict, total=False):
|
|
52
|
+
"""SSL parameters for PostgreSQL connections.
|
|
53
|
+
|
|
54
|
+
All fields are optional. Only includes parameters that can be converted to ssl.SSLContext.
|
|
55
|
+
|
|
56
|
+
Attributes:
|
|
57
|
+
sslmode: SSL mode (disable, allow, prefer, require, verify-ca, verify-full)
|
|
58
|
+
sslrootcert: Path to root CA certificate
|
|
59
|
+
sslcert: Path to client certificate
|
|
60
|
+
sslkey: Path to client private key
|
|
61
|
+
sslpassword: Password for private key
|
|
62
|
+
sslcrl: Path to CRL file
|
|
63
|
+
sslcrldir: Path to CRL directory
|
|
64
|
+
sslsni: Enable SNI (0 or 1)
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
sslmode: str
|
|
68
|
+
sslrootcert: str
|
|
69
|
+
sslcert: str
|
|
70
|
+
sslkey: str
|
|
71
|
+
sslpassword: str
|
|
72
|
+
sslcrl: str
|
|
73
|
+
sslcrldir: str
|
|
74
|
+
sslsni: str
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
_SSL_KEYS: Final[Container[str]] = get_type_hints(_SSLArgs).keys()
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _get_ssl_args(
|
|
81
|
+
query_params: Mapping[str, str | tuple[str, ...]],
|
|
82
|
+
) -> _SSLArgs:
|
|
83
|
+
"""Extract SSL parameters from a SQLAlchemy URL query.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
query_params: SQLAlchemy URL query parameters
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
Dictionary of SSL parameters
|
|
90
|
+
"""
|
|
91
|
+
result: _SSLArgs = {}
|
|
92
|
+
|
|
93
|
+
def get_str(key: str) -> str | None:
|
|
94
|
+
if value := query_params.get(key):
|
|
95
|
+
if not isinstance(value, str):
|
|
96
|
+
raise ValueError(f"Invalid value type for {key}: {type(value)}")
|
|
97
|
+
return value
|
|
98
|
+
return None
|
|
99
|
+
|
|
100
|
+
if sslmode := get_str("sslmode"):
|
|
101
|
+
result["sslmode"] = sslmode
|
|
102
|
+
|
|
103
|
+
if ca_cert := get_str("sslrootcert"):
|
|
104
|
+
result["sslrootcert"] = ca_cert
|
|
105
|
+
|
|
106
|
+
if cert := get_str("sslcert"):
|
|
107
|
+
result["sslcert"] = cert
|
|
108
|
+
|
|
109
|
+
if key := get_str("sslkey"):
|
|
110
|
+
result["sslkey"] = key
|
|
111
|
+
|
|
112
|
+
if password := get_str("sslpassword"):
|
|
113
|
+
result["sslpassword"] = password
|
|
114
|
+
|
|
115
|
+
if crl := get_str("sslcrl"):
|
|
116
|
+
result["sslcrl"] = crl
|
|
117
|
+
|
|
118
|
+
if crl_dir := get_str("sslcrldir"):
|
|
119
|
+
result["sslcrldir"] = crl_dir
|
|
120
|
+
|
|
121
|
+
if sslsni := get_str("sslsni"):
|
|
122
|
+
result["sslsni"] = sslsni
|
|
123
|
+
|
|
124
|
+
return result
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _get_ssl_context(ssl_args: _SSLArgs) -> ssl.SSLContext:
|
|
128
|
+
"""Convert PostgreSQL SSL parameters to an SSL context.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
ssl_args: PostgreSQL SSL parameters from _SSLArgs TypedDict
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
Configured SSL context with:
|
|
135
|
+
- Root CA certificate for server verification (if provided)
|
|
136
|
+
- Client certificate and key for mutual TLS (if provided)
|
|
137
|
+
- SSL mode appropriate verification settings
|
|
138
|
+
- Certificate revocation list checking (if provided)
|
|
139
|
+
"""
|
|
140
|
+
# Create SSL context
|
|
141
|
+
ssl_context = ssl.create_default_context()
|
|
142
|
+
|
|
143
|
+
# Load CA certificate if provided
|
|
144
|
+
if ca_cert := ssl_args.get("sslrootcert"):
|
|
145
|
+
ssl_context.load_verify_locations(cafile=ca_cert)
|
|
146
|
+
|
|
147
|
+
# Load client certificates if provided
|
|
148
|
+
if (cert := ssl_args.get("sslcert")) and (key := ssl_args.get("sslkey")):
|
|
149
|
+
ssl_context.load_cert_chain(
|
|
150
|
+
certfile=cert,
|
|
151
|
+
keyfile=key,
|
|
152
|
+
password=ssl_args.get("sslpassword"),
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# Load CRL if provided
|
|
156
|
+
if crl := ssl_args.get("sslcrl"):
|
|
157
|
+
ssl_context.load_verify_locations(cafile=crl)
|
|
158
|
+
if crl_dir := ssl_args.get("sslcrldir"):
|
|
159
|
+
ssl_context.load_verify_locations(capath=crl_dir)
|
|
160
|
+
|
|
161
|
+
# Set verification mode based on sslmode
|
|
162
|
+
sslmode = ssl_args.get("sslmode", "prefer")
|
|
163
|
+
if sslmode == "verify-full":
|
|
164
|
+
# Full verification: certificate and hostname
|
|
165
|
+
ssl_context.check_hostname = True
|
|
166
|
+
ssl_context.verify_mode = ssl.CERT_REQUIRED
|
|
167
|
+
elif sslmode == "verify-ca":
|
|
168
|
+
# Certificate verification only
|
|
169
|
+
ssl_context.check_hostname = False
|
|
170
|
+
ssl_context.verify_mode = ssl.CERT_REQUIRED
|
|
171
|
+
else: # require, prefer, allow, disable
|
|
172
|
+
# No verification, just encryption
|
|
173
|
+
ssl_context.check_hostname = False
|
|
174
|
+
ssl_context.verify_mode = ssl.CERT_NONE
|
|
175
|
+
|
|
176
|
+
return ssl_context
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _remove_asyncpg_only_params(
|
|
180
|
+
query: Mapping[str, str | tuple[str, ...]],
|
|
181
|
+
) -> dict[str, str | tuple[str, ...]]:
|
|
182
|
+
"""Remove asyncpg-specific parameters from a SQLAlchemy URL query.
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
query: SQLAlchemy URL query parameters
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
Dictionary of query parameters with asyncpg-specific parameters removed
|
|
189
|
+
"""
|
|
190
|
+
return {k: v for k, v in query.items() if k not in _ASYNCPG_ONLY_KEYS}
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
# Asyncpg-specific parameter keys
|
|
194
|
+
_ASYNCPG_ONLY_KEYS: Final[tuple[str, ...]] = (
|
|
195
|
+
"prepared_statement_cache_size",
|
|
196
|
+
# Add other asyncpg-specific parameters here if needed
|
|
197
|
+
)
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_components-
|
|
3
|
-
"file": "assets/components-
|
|
2
|
+
"_components-x-gKFJ8C.js": {
|
|
3
|
+
"file": "assets/components-x-gKFJ8C.js",
|
|
4
4
|
"name": "components",
|
|
5
5
|
"imports": [
|
|
6
6
|
"_vendor-BfhM_F1u.js",
|
|
7
|
-
"_pages-
|
|
7
|
+
"_pages-BU4VdyeH.js",
|
|
8
8
|
"_vendor-arizeai-CxXYQNUl.js",
|
|
9
9
|
"_vendor-codemirror-B0NIFPOL.js",
|
|
10
10
|
"_vendor-three-C5WAXd5r.js"
|
|
11
11
|
]
|
|
12
12
|
},
|
|
13
|
-
"_pages-
|
|
14
|
-
"file": "assets/pages-
|
|
13
|
+
"_pages-BU4VdyeH.js": {
|
|
14
|
+
"file": "assets/pages-BU4VdyeH.js",
|
|
15
15
|
"name": "pages",
|
|
16
16
|
"imports": [
|
|
17
17
|
"_vendor-BfhM_F1u.js",
|
|
18
18
|
"_vendor-arizeai-CxXYQNUl.js",
|
|
19
|
-
"_components-
|
|
19
|
+
"_components-x-gKFJ8C.js",
|
|
20
20
|
"_vendor-codemirror-B0NIFPOL.js",
|
|
21
21
|
"_vendor-recharts-CrrDFWK1.js"
|
|
22
22
|
]
|
|
@@ -69,15 +69,15 @@
|
|
|
69
69
|
"name": "vendor-three"
|
|
70
70
|
},
|
|
71
71
|
"index.tsx": {
|
|
72
|
-
"file": "assets/index-
|
|
72
|
+
"file": "assets/index-B0CbpsxD.js",
|
|
73
73
|
"name": "index",
|
|
74
74
|
"src": "index.tsx",
|
|
75
75
|
"isEntry": true,
|
|
76
76
|
"imports": [
|
|
77
77
|
"_vendor-BfhM_F1u.js",
|
|
78
78
|
"_vendor-arizeai-CxXYQNUl.js",
|
|
79
|
-
"_pages-
|
|
80
|
-
"_components-
|
|
79
|
+
"_pages-BU4VdyeH.js",
|
|
80
|
+
"_components-x-gKFJ8C.js",
|
|
81
81
|
"_vendor-three-C5WAXd5r.js",
|
|
82
82
|
"_vendor-codemirror-B0NIFPOL.js",
|
|
83
83
|
"_vendor-shiki-C5bJ-RPf.js",
|