diff --git a/.github/actions/test-data-asyncio/action.yaml b/.github/actions/test-data-asyncio/action.yaml index 0b4469ff..fb349ca9 100644 --- a/.github/actions/test-data-asyncio/action.yaml +++ b/.github/actions/test-data-asyncio/action.yaml @@ -38,7 +38,7 @@ runs: - name: Run data plane tests id: data-plane-asyncio-tests shell: bash - run: poetry run pytest tests/integration/data_asyncio -s -vv + run: poetry run pytest tests/integration/data_asyncio --retries 5 --retry-delay 35 -s -vv --log-cli-level=DEBUG env: PINECONE_API_KEY: ${{ inputs.PINECONE_API_KEY }} USE_GRPC: ${{ inputs.use_grpc }} diff --git a/.github/actions/test-data-plane/action.yaml b/.github/actions/test-data-plane/action.yaml index e11aed58..3a1c1204 100644 --- a/.github/actions/test-data-plane/action.yaml +++ b/.github/actions/test-data-plane/action.yaml @@ -52,7 +52,7 @@ runs: - name: Run data plane tests id: data-plane-tests shell: bash - run: poetry run pytest tests/integration/data + run: poetry run pytest tests/integration/data --retries 5 --retry-delay 35 -s -vv --log-cli-level=DEBUG env: PINECONE_API_KEY: ${{ inputs.PINECONE_API_KEY }} USE_GRPC: ${{ inputs.use_grpc }} diff --git a/.github/workflows/testing-integration-asyncio.yaml b/.github/workflows/testing-integration-asyncio.yaml index 4508a385..8c8fab60 100644 --- a/.github/workflows/testing-integration-asyncio.yaml +++ b/.github/workflows/testing-integration-asyncio.yaml @@ -26,7 +26,7 @@ jobs: - name: Run data plane tests id: data-plane-asyncio-tests shell: bash - run: poetry run pytest tests/integration/data_asyncio -s -vv + run: poetry run pytest tests/integration/data_asyncio --retries 5 --retry-delay 35 -s -vv --log-cli-level=DEBUG env: PINECONE_API_KEY: ${{ secrets.PINECONE_API_KEY }} @@ -51,6 +51,6 @@ jobs: include_asyncio: true include_dev: true - name: 'db_control asyncio' - run: poetry run pytest tests/integration/control_asyncio -s -vv + run: poetry run pytest tests/integration/control_asyncio --retries 5 --retry-delay 35 -s -vv --log-cli-level=DEBUG env: PINECONE_API_KEY: '${{ secrets.PINECONE_API_KEY }}' diff --git a/.github/workflows/testing-integration.yaml b/.github/workflows/testing-integration.yaml index fceb1422..8275a5f1 100644 --- a/.github/workflows/testing-integration.yaml +++ b/.github/workflows/testing-integration.yaml @@ -21,7 +21,7 @@ jobs: with: include_asyncio: true - name: 'Run integration tests' - run: poetry run pytest tests/integration/inference -s -vv + run: poetry run pytest tests/integration/inference --retries 5 --retry-delay 35 -s -vv --log-cli-level=DEBUG env: PINECONE_DEBUG_CURL: 'true' PINECONE_API_KEY: '${{ secrets.PINECONE_API_KEY }}' @@ -113,7 +113,7 @@ jobs: - name: Setup Poetry uses: ./.github/actions/setup-poetry - name: 'Run integration tests (REST)' - run: poetry run pytest tests/integration/control/serverless -s -vv + run: poetry run pytest tests/integration/control/serverless --retries 5 --retry-delay 35 -s -vv --log-cli-level=DEBUG env: PINECONE_DEBUG_CURL: 'true' PINECONE_API_KEY: '${{ secrets.PINECONE_API_KEY }}' diff --git a/.github/workflows/testing-unit.yaml b/.github/workflows/testing-unit.yaml index 9ee0bbb9..f97dfacf 100644 --- a/.github/workflows/testing-unit.yaml +++ b/.github/workflows/testing-unit.yaml @@ -58,7 +58,7 @@ jobs: include_asyncio: true - name: Run unit tests (REST) - run: poetry run pytest --cov=pinecone --timeout=120 tests/unit + run: poetry run pytest --cov=pinecone --timeout=120 tests/unit --retries 5 --retry-delay 35 -s -vv --log-cli-level=DEBUG - name: Run unit tests (GRPC) if: ${{ matrix.use_grpc == true }} - run: poetry run pytest --cov=pinecone/grpc --timeout=120 tests/unit_grpc + run: poetry run pytest --cov=pinecone/grpc --timeout=120 tests/unit_grpc --retries 5 --retry-delay 35 -s -vv --log-cli-level=DEBUG diff --git a/pinecone/grpc/utils.py b/pinecone/grpc/utils.py index bd6540de..dcd19710 100644 --- a/pinecone/grpc/utils.py +++ b/pinecone/grpc/utils.py @@ -48,8 +48,8 @@ def parse_fetch_response(response: Message): for id, vec in vectors.items(): vd[id] = _Vector( id=vec["id"], - values=vec["values"], - sparse_values=parse_sparse_values(vec.get("sparseValues")), + values=vec.get("values", None), + sparse_values=parse_sparse_values(vec.get("sparseValues", None)), metadata=vec.get("metadata", None), _check_type=False, ) diff --git a/pinecone/utils/tqdm.py b/pinecone/utils/tqdm.py index 05907686..df1f34a3 100644 --- a/pinecone/utils/tqdm.py +++ b/pinecone/utils/tqdm.py @@ -1,6 +1,12 @@ +import warnings + +__all__ = ["tqdm"] + try: - # Use the notebook-friendly auto selection if tqdm is installed. - from tqdm.auto import tqdm + # Suppress the specific tqdm warning about IProgress + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=UserWarning, module="tqdm") + from tqdm.auto import tqdm except ImportError: # Fallback: define a dummy tqdm that supports the same interface. class tqdm: # type: ignore diff --git a/poetry.lock b/poetry.lock index 8805fbf9..427dc1e2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1452,6 +1452,23 @@ pytest = ">=5.0" [package.extras] dev = ["pre-commit", "pytest-asyncio", "tox"] +[[package]] +name = "pytest-retry" +version = "1.7.0" +description = "Adds the ability to retry flaky tests in CI environments" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pytest_retry-1.7.0-py3-none-any.whl", hash = "sha256:a2dac85b79a4e2375943f1429479c65beb6c69553e7dae6b8332be47a60954f4"}, + {file = "pytest_retry-1.7.0.tar.gz", hash = "sha256:f8d52339f01e949df47c11ba9ee8d5b362f5824dff580d3870ec9ae0057df80f"}, +] + +[package.dependencies] +pytest = ">=7.0.0" + +[package.extras] +dev = ["black", "flake8", "isort", "mypy"] + [[package]] name = "pytest-timeout" version = "2.2.0" @@ -1882,4 +1899,4 @@ grpc = ["googleapis-common-protos", "grpcio", "grpcio", "grpcio", "lz4", "protob [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "bf919c64ad5ce7179d48c97ab8b608e49671ce20db9ed660121e99eea9d574cc" +content-hash = "8a10046c5826a9773836e6b3ee50271bb0077d0faf32d709f1e65c4bb1fc53ea" diff --git a/pyproject.toml b/pyproject.toml index 9f81f8c9..891066a3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -85,6 +85,7 @@ pytest = "8.2.0" pytest-asyncio = "^0.25.2" pytest-cov = "2.10.1" pytest-mock = "3.6.1" +pytest-retry = "^1.7.0" pytest-timeout = "2.2.0" pytest-benchmark = [ { version = '5.0.0', python = ">=3.9,<4.0" } diff --git a/tests/integration/data/test_fetch.py b/tests/integration/data/test_fetch.py index 5523d27e..7c97aa9e 100644 --- a/tests/integration/data/test_fetch.py +++ b/tests/integration/data/test_fetch.py @@ -143,7 +143,6 @@ def test_fetch_unspecified_namespace(self, idx): assert results.vectors["1"].values is not None assert results.vectors["4"].metadata is not None - @pytest.mark.skip(reason="Backend implementation not ready") def test_fetch_sparse_index(self, sparse_idx): sparse_idx.upsert( vectors=[ @@ -165,9 +164,11 @@ def test_fetch_sparse_index(self, sparse_idx): assert fetch_results.namespace == "" assert len(fetch_results.vectors) == 10 for i in range(10): + logger.debug(fetch_results.vectors[str(i)]) assert fetch_results.vectors[str(i)].id == str(i) - assert fetch_results.vectors[str(i)].values is not None - assert len(fetch_results.vectors[str(i)].values) == 2 + assert fetch_results.vectors[str(i)].sparse_values is not None + assert len(fetch_results.vectors[str(i)].sparse_values.indices) == 2 + assert len(fetch_results.vectors[str(i)].sparse_values.values) == 2 assert fetch_results.vectors[str(i)].metadata is not None assert fetch_results.vectors[str(i)].metadata["genre"] == "action" assert fetch_results.vectors[str(i)].metadata["runtime"] == 120 diff --git a/tests/integration/data/test_list_errors.py b/tests/integration/data/test_list_errors.py index 1ab3c496..bda299a0 100644 --- a/tests/integration/data/test_list_errors.py +++ b/tests/integration/data/test_list_errors.py @@ -28,6 +28,7 @@ def seed_for_list2(idx, list_errors_namespace, wait=True): @pytest.mark.usefixtures("seed_for_list2") class TestListErrors: + @pytest.mark.skip(reason="Bug filed https://github.com/pinecone-io/pinecone-db/issues/9578") def test_list_change_prefix_while_fetching_next_page(self, idx, list_errors_namespace): results = idx.list_paginated(prefix="99", limit=5, namespace=list_errors_namespace) with pytest.raises(PineconeException) as e: diff --git a/tests/integration/data/test_query.py b/tests/integration/data/test_query.py index 09f895c2..99971f8d 100644 --- a/tests/integration/data/test_query.py +++ b/tests/integration/data/test_query.py @@ -115,7 +115,11 @@ def test_query_by_vector_include_metadata(self, idx, query_namespace, use_nondef assert isinstance(results, QueryResponse) == True assert results.namespace == target_namespace - matches_with_metadata = [match for match in results.matches if match.metadata is not None] + matches_with_metadata = [ + match + for match in results.matches + if match.metadata is not None and match.metadata != {} + ] assert len(matches_with_metadata) == 3 assert find_by_id(results.matches, "4").metadata["genre"] == "action" @@ -134,7 +138,11 @@ def test_query_by_vector_include_values_and_metadata( assert isinstance(results, QueryResponse) == True assert results.namespace == target_namespace - matches_with_metadata = [match for match in results.matches if match.metadata is not None] + matches_with_metadata = [ + match + for match in results.matches + if match.metadata is not None and match.metadata != {} + ] assert len(matches_with_metadata) == 3 assert find_by_id(results.matches, "4").metadata["genre"] == "action" assert len(results.matches[0].values) == self.expected_dimension