Skip to content

Commit 4415ff8

Browse files
committed
feat(preview): add private_host, source_collection, source_backup_id, cmek_id to PreviewIndexModel
## Purpose Four optional fields present in backend GlobalIndexMetadata were not exposed on PreviewIndexModel, so callers had no way to read them even though msgspec silently discarded the values. ## Solution Added all four as optional fields with `= None` defaults after `tags`: - `private_host` — private-network data-plane host when private endpoints are configured - `source_collection` — collection this index was created from (if any) - `source_backup_id` — backup this index was created from (if any) - `cmek_id` — customer-managed encryption key ID (if any) Updated `__repr__` and `_repr_pretty_` to conditionally include `private_host` when set. Added five unit tests covering all four fields present, all absent, partial, and repr rendering.
1 parent 182e6d3 commit 4415ff8

2 files changed

Lines changed: 91 additions & 0 deletions

File tree

pinecone/preview/models/indexes.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ class PreviewIndexModel(Struct, kw_only=True):
3838
read_capacity: Read capacity configuration, or ``None`` for the
3939
default on-demand mode.
4040
tags: User-defined key-value tags, or ``None``.
41+
private_host: Private-network hostname for the index data plane, or
42+
``None`` when private endpoints are not configured for the project.
43+
source_collection: Name of the collection this index was created from,
44+
or ``None`` if not created from a collection.
45+
source_backup_id: ID of the backup this index was created from, or
46+
``None`` if not created from a backup.
47+
cmek_id: ID of the customer-managed encryption key protecting this
48+
index, or ``None`` if CMEK is not configured.
4149
"""
4250

4351
name: str
@@ -48,6 +56,10 @@ class PreviewIndexModel(Struct, kw_only=True):
4856
host: str | None = None
4957
read_capacity: PreviewReadCapacity | None = None
5058
tags: dict[str, str] | None = None
59+
private_host: str | None = None
60+
source_collection: str | None = None
61+
source_backup_id: str | None = None
62+
cmek_id: str | None = None
5163

5264
def __repr__(self) -> str:
5365
dep_name = type(self.deployment).__name__.replace("Deployment", "")
@@ -62,6 +74,8 @@ def __repr__(self) -> str:
6274
parts.append(f"schema_fields={len(self.schema.fields)}")
6375
if self.tags:
6476
parts.append(f"tags={len(self.tags)} items")
77+
if self.private_host is not None:
78+
parts.append(f"private_host={self.private_host!r}")
6579
return f"PreviewIndexModel({', '.join(parts)})"
6680

6781
def __dir__(self) -> list[str]:
@@ -94,6 +108,9 @@ def _repr_pretty_(self, p: Any, cycle: bool) -> None:
94108
if self.tags:
95109
p.breakable()
96110
p.text(f"tags={self.tags!r},")
111+
if self.private_host is not None:
112+
p.breakable()
113+
p.text(f"private_host={self.private_host!r},")
97114

98115
def _repr_html_(self) -> str:
99116
"""Jupyter notebook HTML representation."""
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
"""Unit tests for PreviewIndexModel optional response fields."""
2+
3+
from __future__ import annotations
4+
5+
import msgspec
6+
7+
from pinecone.preview.models.indexes import PreviewIndexModel
8+
9+
_BASE_RAW = (
10+
b'{"name":"idx","host":"idx.svc.pinecone.io",'
11+
b'"status":{"state":"Ready","ready":true},'
12+
b'"schema":{"fields":{}},'
13+
b'"deployment":{"deployment_type":"managed","cloud":"aws","region":"us-east-1"},'
14+
b'"deletion_protection":"disabled"'
15+
)
16+
17+
18+
def test_preview_index_model_optional_response_fields() -> None:
19+
raw = (
20+
b'{"name":"idx","host":"idx.svc.pinecone.io",'
21+
b'"status":{"state":"Ready","ready":true},'
22+
b'"schema":{"fields":{}},'
23+
b'"deployment":{"deployment_type":"managed","cloud":"aws","region":"us-east-1"},'
24+
b'"deletion_protection":"disabled",'
25+
b'"private_host":"idx.svc.private.pinecone.io",'
26+
b'"source_collection":"my-collection",'
27+
b'"source_backup_id":"bkp-abc123",'
28+
b'"cmek_id":"cmek-xyz789"}'
29+
)
30+
model = msgspec.json.decode(raw, type=PreviewIndexModel)
31+
assert model.private_host == "idx.svc.private.pinecone.io"
32+
assert model.source_collection == "my-collection"
33+
assert model.source_backup_id == "bkp-abc123"
34+
assert model.cmek_id == "cmek-xyz789"
35+
36+
37+
def test_preview_index_model_optional_response_fields_absent() -> None:
38+
"""Fields are None when absent from the response."""
39+
raw = _BASE_RAW + b"}"
40+
model = msgspec.json.decode(raw, type=PreviewIndexModel)
41+
assert model.private_host is None
42+
assert model.source_collection is None
43+
assert model.source_backup_id is None
44+
assert model.cmek_id is None
45+
46+
47+
def test_preview_index_model_repr_includes_private_host_when_set() -> None:
48+
raw = _BASE_RAW + b',"private_host":"idx.svc.private.pinecone.io"}'
49+
model = msgspec.json.decode(raw, type=PreviewIndexModel)
50+
assert "private_host=" in repr(model)
51+
assert "idx.svc.private.pinecone.io" in repr(model)
52+
53+
54+
def test_preview_index_model_repr_omits_private_host_when_absent() -> None:
55+
raw = _BASE_RAW + b"}"
56+
model = msgspec.json.decode(raw, type=PreviewIndexModel)
57+
assert "private_host" not in repr(model)
58+
59+
60+
def test_preview_index_model_partial_optional_fields() -> None:
61+
"""Only some optional fields present — the rest remain None."""
62+
raw = (
63+
b'{"name":"idx","host":"idx.svc.pinecone.io",'
64+
b'"status":{"state":"Ready","ready":true},'
65+
b'"schema":{"fields":{}},'
66+
b'"deployment":{"deployment_type":"managed","cloud":"aws","region":"us-east-1"},'
67+
b'"deletion_protection":"disabled",'
68+
b'"source_collection":"col-1"}'
69+
)
70+
model = msgspec.json.decode(raw, type=PreviewIndexModel)
71+
assert model.source_collection == "col-1"
72+
assert model.private_host is None
73+
assert model.source_backup_id is None
74+
assert model.cmek_id is None

0 commit comments

Comments
 (0)