Skip to content

Commit 68b76cc

Browse files
committed
Cleanup test resources
1 parent 6efd333 commit 68b76cc

File tree

4 files changed

+183
-30
lines changed

4 files changed

+183
-30
lines changed

scripts/repl.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import code
33
from pinecone import Pinecone
44
import logging
5+
import os
56

67

78
def main():
@@ -15,18 +16,66 @@ def main():
1516
logging.basicConfig(
1617
level=logging.DEBUG, format="%(levelname)-8s | %(name)s:%(lineno)d | %(message)s"
1718
)
19+
logger = logging.getLogger(__name__)
1820

1921
# Start the interactive REPL
2022
banner = """
2123
Welcome to the custom Python REPL!
2224
Your initialization steps have been completed.
25+
26+
Two Pinecone objects are available:
27+
- pc: Interact with the one-offs project
28+
- pcci: Interact with the pinecone-python-client project (CI testing)
29+
30+
You can use the following functions to clean up the environment:
31+
- delete_all_indexes(pc)
32+
- delete_all_collections(pc)
33+
- delete_all_backups(pc)
34+
- cleanup_all(pc)
2335
"""
2436

37+
def delete_all_indexes(pc):
38+
for index in pc.db.index.list():
39+
logger.info(f"Deleting index {index.name}")
40+
try:
41+
if index.deletion_protection == "enabled":
42+
logger.info(f"Disabling deletion protection for index {index.name}")
43+
pc.db.index.configure(name=index.name, deletion_protection="disabled")
44+
pc.db.index.delete(name=index.name)
45+
except Exception as e:
46+
logger.error(f"Error deleting index {index.name}: {e}")
47+
48+
def delete_all_collections(pc):
49+
for collection in pc.db.collection.list():
50+
logger.info(f"Deleting collection {collection.name}")
51+
try:
52+
pc.db.collection.delete(name=collection.name)
53+
except Exception as e:
54+
logger.error(f"Error deleting collection {collection.name}: {e}")
55+
56+
def delete_all_backups(pc):
57+
for backup in pc.db.backup.list():
58+
logger.info(f"Deleting backup {backup.name}")
59+
try:
60+
pc.db.backup.delete(backup_id=backup.backup_id)
61+
except Exception as e:
62+
logger.error(f"Error deleting backup {backup.name}: {e}")
63+
64+
def cleanup_all(pc):
65+
delete_all_indexes(pc)
66+
delete_all_collections(pc)
67+
delete_all_backups(pc)
68+
2569
# Create a custom namespace with any pre-loaded variables
2670
namespace = {
2771
"__name__": "__main__",
2872
"__doc__": None,
2973
"pc": Pinecone(),
74+
"pcci": Pinecone(api_key=os.environ.get("PINECONE_API_KEY_CI_TESTING")),
75+
"delete_all_indexes": delete_all_indexes,
76+
"delete_all_collections": delete_all_collections,
77+
"delete_all_backups": delete_all_backups,
78+
"cleanup_all": cleanup_all,
3079
# Add any other variables you want to have available in the REPL
3180
}
3281

tests/integration/control/resources/index/test_create.py

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@
1717

1818

1919
class TestCreateServerlessIndexHappyPath:
20-
def test_create_index(self, pc: Pinecone, index_name):
20+
def test_create_index(self, pc: Pinecone, index_name, index_tags):
2121
resp = pc.db.index.create(
2222
name=index_name,
2323
dimension=10,
2424
spec=ServerlessSpec(cloud=CloudProvider.AWS, region=AwsRegion.US_EAST_1),
25+
tags=index_tags,
2526
)
2627
assert resp.name == index_name
2728
assert resp.dimension == 10
@@ -36,23 +37,25 @@ def test_create_index(self, pc: Pinecone, index_name):
3637
assert desc.deletion_protection == "disabled" # default value
3738
assert desc.vector_type == "dense" # default value
3839

39-
def test_create_skip_wait(self, pc, index_name):
40+
def test_create_skip_wait(self, pc, index_name, index_tags):
4041
resp = pc.db.index.create(
4142
name=index_name,
4243
dimension=10,
4344
spec=ServerlessSpec(cloud=CloudProvider.AWS, region=AwsRegion.US_EAST_1),
4445
timeout=-1,
46+
tags=index_tags,
4547
)
4648
assert resp.name == index_name
4749
assert resp.dimension == 10
4850
assert resp.metric == "cosine"
4951

50-
def test_create_infinite_wait(self, pc, index_name):
52+
def test_create_infinite_wait(self, pc, index_name, index_tags):
5153
resp = pc.db.index.create(
5254
name=index_name,
5355
dimension=10,
5456
spec=ServerlessSpec(cloud=CloudProvider.AWS, region=AwsRegion.US_EAST_1),
5557
timeout=None,
58+
tags=index_tags,
5659
)
5760
assert resp.name == index_name
5861
assert resp.dimension == 10
@@ -70,23 +73,23 @@ def test_create_default_index_with_metric(self, pc, create_index_params, metric)
7073
assert desc.vector_type == "dense"
7174

7275
@pytest.mark.parametrize(
73-
"metric_enum,vector_type_enum,dim,tags",
76+
"metric_enum,vector_type_enum,dim",
7477
[
75-
(Metric.COSINE, VectorType.DENSE, 10, None),
76-
(Metric.EUCLIDEAN, VectorType.DENSE, 10, {"env": "prod"}),
77-
(Metric.DOTPRODUCT, VectorType.SPARSE, None, {"env": "dev"}),
78+
(Metric.COSINE, VectorType.DENSE, 10),
79+
(Metric.EUCLIDEAN, VectorType.DENSE, 10),
80+
(Metric.DOTPRODUCT, VectorType.SPARSE, None),
7881
],
7982
)
8083
def test_create_with_enum_values(
81-
self, pc, index_name, metric_enum, vector_type_enum, dim, tags
84+
self, pc, index_name, metric_enum, vector_type_enum, dim, index_tags
8285
):
8386
args = {
8487
"name": index_name,
8588
"metric": metric_enum,
8689
"vector_type": vector_type_enum,
8790
"deletion_protection": DeletionProtection.DISABLED,
8891
"spec": ServerlessSpec(cloud=CloudProvider.AWS, region=AwsRegion.US_EAST_1),
89-
"tags": tags,
92+
"tags": index_tags,
9093
}
9194
if dim is not None:
9295
args["dimension"] = dim
@@ -101,8 +104,7 @@ def test_create_with_enum_values(
101104
assert desc.name == index_name
102105
assert desc.spec.serverless.cloud == "aws"
103106
assert desc.spec.serverless.region == "us-east-1"
104-
if tags:
105-
assert desc.tags.to_dict() == tags
107+
assert desc.tags.to_dict() == index_tags
106108

107109
@pytest.mark.parametrize("metric", ["cosine", "euclidean", "dotproduct"])
108110
def test_create_dense_index_with_metric(self, pc, create_index_params, metric):
@@ -113,13 +115,6 @@ def test_create_dense_index_with_metric(self, pc, create_index_params, metric):
113115
assert desc.metric == metric
114116
assert desc.vector_type == "dense"
115117

116-
def test_create_with_optional_tags(self, pc, create_index_params):
117-
tags = {"foo": "FOO", "bar": "BAR"}
118-
create_index_params["tags"] = tags
119-
pc.db.index.create(**create_index_params)
120-
desc = pc.db.index.describe(create_index_params["name"])
121-
assert desc.tags.to_dict() == tags
122-
123118

124119
class TestCreatePodIndexHappyPath:
125120
def test_create_index_minimal_config(
@@ -152,7 +147,7 @@ def test_create_index_with_spec_options(
152147
metric="cosine",
153148
spec=PodSpec(
154149
environment=pod_environment,
155-
pod_type="p1.x2",
150+
pod_type="p1.x1",
156151
replicas=2,
157152
metadata_config={"indexed": ["foo", "bar"]},
158153
),
@@ -164,9 +159,10 @@ def test_create_index_with_spec_options(
164159
assert desc.dimension == 10
165160
assert desc.metric == "cosine"
166161
assert desc.spec.pod.environment == pod_environment
167-
assert desc.spec.pod.pod_type == "p1.x2"
162+
assert desc.spec.pod.pod_type == "p1.x1"
168163
assert desc.spec.pod.replicas == 2
169164
assert desc.spec.pod.metadata_config.indexed == ["foo", "bar"]
165+
assert desc.tags.to_dict() == index_tags
170166

171167
def test_create_index_with_deletion_protection(
172168
self, pc: Pinecone, index_name, pod_environment, index_tags

tests/integration/control_asyncio/resources/index/test_create.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
@pytest.mark.asyncio
1414
class TestAsyncioCreateIndex:
1515
@pytest.mark.parametrize("spec_fixture", ("spec1", "spec2", "spec3"))
16-
async def test_create_index(self, index_name, request, spec_fixture):
16+
async def test_create_index(self, index_name, request, spec_fixture, index_tags):
1717
pc = PineconeAsyncio()
1818
spec = request.getfixturevalue(spec_fixture)
1919

20-
resp = await pc.db.index.create(name=index_name, dimension=10, spec=spec)
20+
resp = await pc.db.index.create(name=index_name, dimension=10, spec=spec, tags=index_tags)
2121

2222
assert resp.name == index_name
2323
assert resp.dimension == 10
@@ -33,17 +33,21 @@ async def test_create_index(self, index_name, request, spec_fixture):
3333
assert desc.vector_type == "dense" # default value
3434
await pc.close()
3535

36-
async def test_create_skip_wait(self, index_name, spec1):
36+
async def test_create_skip_wait(self, index_name, spec1, index_tags):
3737
pc = PineconeAsyncio()
38-
resp = await pc.db.index.create(name=index_name, dimension=10, spec=spec1, timeout=-1)
38+
resp = await pc.db.index.create(
39+
name=index_name, dimension=10, spec=spec1, timeout=-1, tags=index_tags
40+
)
3941
assert resp.name == index_name
4042
assert resp.dimension == 10
4143
assert resp.metric == "cosine"
4244
await pc.close()
4345

44-
async def test_create_infinite_wait(self, index_name, spec1):
46+
async def test_create_infinite_wait(self, index_name, spec1, index_tags):
4547
async with PineconeAsyncio() as pc:
46-
resp = await pc.db.index.create(name=index_name, dimension=10, spec=spec1, timeout=None)
48+
resp = await pc.db.index.create(
49+
name=index_name, dimension=10, spec=spec1, timeout=None, tags=index_tags
50+
)
4751
assert resp.name == index_name
4852
assert resp.dimension == 10
4953
assert resp.metric == "cosine"
@@ -104,7 +108,7 @@ async def test_create_with_enum_values_and_tags(
104108
async def test_create_dense_index_with_metric(self, index_name, spec1, metric, index_tags):
105109
pc = PineconeAsyncio()
106110

107-
await pc.create_index(
111+
await pc.db.index.create(
108112
name=index_name,
109113
dimension=10,
110114
spec=spec1,
@@ -121,7 +125,7 @@ async def test_create_dense_index_with_metric(self, index_name, spec1, metric, i
121125
async def test_create_with_optional_tags(self, index_name, spec1, index_tags):
122126
pc = PineconeAsyncio()
123127

124-
await pc.create_index(name=index_name, dimension=10, spec=spec1, tags=index_tags)
128+
await pc.db.index.create(name=index_name, dimension=10, spec=spec1, tags=index_tags)
125129

126130
desc = await pc.db.index.describe(name=index_name)
127131
assert desc.tags.to_dict() == index_tags
@@ -131,7 +135,7 @@ async def test_create_with_optional_tags(self, index_name, spec1, index_tags):
131135
async def test_create_sparse_index(self, index_name, spec1, index_tags):
132136
pc = PineconeAsyncio()
133137

134-
await pc.create_index(
138+
await pc.db.index.create(
135139
name=index_name,
136140
spec=spec1,
137141
metric=Metric.DOTPRODUCT,
@@ -149,7 +153,7 @@ async def test_create_sparse_index(self, index_name, spec1, index_tags):
149153
async def test_create_with_deletion_protection(self, index_name, spec1, index_tags):
150154
pc = PineconeAsyncio()
151155

152-
await pc.create_index(
156+
await pc.db.index.create(
153157
name=index_name,
154158
spec=spec1,
155159
metric=Metric.DOTPRODUCT,

tests/unit/test_rest_urllib3.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import pytest
2+
from unittest.mock import patch, MagicMock
3+
import urllib3
4+
from urllib3.exceptions import MaxRetryError
5+
from pinecone.openapi_support.rest_urllib3 import Urllib3RestClient
6+
from pinecone.config.openapi_configuration import Configuration
7+
8+
9+
class TestUrllib3RestClient:
10+
@pytest.fixture
11+
def config(self):
12+
return Configuration(api_key="test-key")
13+
14+
@pytest.fixture
15+
def client(self, config):
16+
return Urllib3RestClient(config)
17+
18+
def test_retry_on_500_error(self, client):
19+
# Mock response that fails with 500
20+
mock_response = MagicMock()
21+
mock_response.status = 500
22+
mock_response.data = b'{"error": "Internal Server Error"}'
23+
mock_response.headers = {}
24+
mock_response.reason = "Internal Server Error"
25+
26+
# Mock pool manager to fail twice then succeed
27+
with patch.object(client.pool_manager, "request") as mock_request:
28+
mock_request.side_effect = [
29+
urllib3.exceptions.HTTPError(response=mock_response),
30+
urllib3.exceptions.HTTPError(response=mock_response),
31+
mock_response, # Success on third try
32+
]
33+
34+
# Make request
35+
response = client.request(
36+
method="GET",
37+
url="https://api.pinecone.io/test",
38+
headers={"Authorization": "test-key"},
39+
)
40+
41+
# Verify request was made 3 times (initial + 2 retries)
42+
assert mock_request.call_count == 3
43+
44+
# Verify the response is successful
45+
assert response.status == 200
46+
47+
def test_max_retries_exceeded(self, client):
48+
# Mock response that always fails with 500
49+
mock_response = MagicMock()
50+
mock_response.status = 500
51+
mock_response.data = b'{"error": "Internal Server Error"}'
52+
mock_response.headers = {}
53+
mock_response.reason = "Internal Server Error"
54+
55+
# Mock pool manager to always fail
56+
with patch.object(client.pool_manager, "request") as mock_request:
57+
mock_request.side_effect = urllib3.exceptions.HTTPError(response=mock_response)
58+
59+
# Make request and expect MaxRetryError
60+
with pytest.raises(MaxRetryError):
61+
client.request(
62+
method="GET",
63+
url="https://api.pinecone.io/test",
64+
headers={"Authorization": "test-key"},
65+
)
66+
67+
# Verify request was made 4 times (initial + 3 retries)
68+
assert mock_request.call_count == 4
69+
70+
def test_custom_retry_config(self):
71+
# Create custom retry configuration
72+
custom_retry = urllib3.Retry(
73+
total=2, backoff_factor=0.5, status_forcelist=(500, 502, 503, 504)
74+
)
75+
76+
config = Configuration(api_key="test-key", retries=custom_retry)
77+
client = Urllib3RestClient(config)
78+
79+
# Mock response that fails with 500
80+
mock_response = MagicMock()
81+
mock_response.status = 500
82+
mock_response.data = b'{"error": "Internal Server Error"}'
83+
mock_response.headers = {}
84+
mock_response.reason = "Internal Server Error"
85+
86+
# Mock pool manager to fail once then succeed
87+
with patch.object(client.pool_manager, "request") as mock_request:
88+
mock_request.side_effect = [
89+
urllib3.exceptions.HTTPError(response=mock_response),
90+
mock_response, # Success on second try
91+
]
92+
93+
# Make request
94+
response = client.request(
95+
method="GET",
96+
url="https://api.pinecone.io/test",
97+
headers={"Authorization": "test-key"},
98+
)
99+
100+
# Verify request was made 2 times (initial + 1 retry)
101+
assert mock_request.call_count == 2
102+
103+
# Verify the response is successful
104+
assert response.status == 200

0 commit comments

Comments
 (0)