pgvector-haystack 8.0.0__tar.gz → 8.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.
Files changed (27) hide show
  1. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/CHANGELOG.md +12 -0
  2. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/PKG-INFO +1 -1
  3. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/src/haystack_integrations/document_stores/pgvector/document_store.py +43 -20
  4. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/tests/test_document_store.py +21 -0
  5. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/tests/test_document_store_async.py +27 -0
  6. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/.gitignore +0 -0
  7. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/LICENSE.txt +0 -0
  8. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/README.md +0 -0
  9. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/examples/embedding_retrieval.py +0 -0
  10. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/examples/hybrid_retrieval.py +0 -0
  11. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/pydoc/config_docusaurus.yml +0 -0
  12. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/pyproject.toml +0 -0
  13. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/src/haystack_integrations/components/retrievers/pgvector/__init__.py +0 -0
  14. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/src/haystack_integrations/components/retrievers/pgvector/embedding_retriever.py +0 -0
  15. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/src/haystack_integrations/components/retrievers/pgvector/keyword_retriever.py +0 -0
  16. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/src/haystack_integrations/components/retrievers/py.typed +0 -0
  17. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/src/haystack_integrations/document_stores/pgvector/__init__.py +0 -0
  18. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/src/haystack_integrations/document_stores/pgvector/converters.py +0 -0
  19. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/src/haystack_integrations/document_stores/pgvector/filters.py +0 -0
  20. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/src/haystack_integrations/document_stores/py.typed +0 -0
  21. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/tests/__init__.py +0 -0
  22. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/tests/conftest.py +0 -0
  23. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/tests/test_converters.py +0 -0
  24. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/tests/test_filters.py +0 -0
  25. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/tests/test_retrieval.py +0 -0
  26. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/tests/test_retrieval_async.py +0 -0
  27. {pgvector_haystack-8.0.0 → pgvector_haystack-8.1.0}/tests/test_retrievers.py +0 -0
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [integrations/pgvector-v8.0.0] - 2026-10-16
4
+
5
+ ### 🧪 Testing
6
+
7
+ - Test compatible integrations with Python 3.15; update pyproject (#4104)
8
+
9
+ ### 🧹 Chores
10
+
11
+ - Drop redundant deserialize_secrets_inplace calls in integrations requiring haystack-ai>=2.23 (#4058)
12
+ - [**breaking**] Drop Python 3.10 support (#4105)
13
+
14
+
3
15
  ## [integrations/pgvector-v7.0.0] - 2026-09-29
4
16
 
5
17
  ### 🐛 Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pgvector-haystack
3
- Version: 8.0.0
3
+ Version: 8.1.0
4
4
  Summary: An integration of pgvector (vector search extension for Postgres) with Haystack
5
5
  Project-URL: Source, https://github.com/deepset-ai/haystack-core-integrations
6
6
  Project-URL: Documentation, https://github.com/deepset-ai/haystack-core-integrations/blob/main/integrations/pgvector/README.md
@@ -370,6 +370,47 @@ class PgvectorDocumentStore:
370
370
 
371
371
  return result
372
372
 
373
+ def _create_connection(self) -> Connection:
374
+ """
375
+ Opens a new connection to the PostgreSQL database.
376
+
377
+ Subclasses can override this method to connect differently (e.g. through a cloud provider's connector).
378
+ It must only open and return the connection: autocommit, the pgvector extension, vector type
379
+ registration, cursors, and table initialization are handled by `_ensure_db_setup`.
380
+
381
+ :raises DocumentStoreError: If the connection cannot be opened.
382
+ """
383
+ conn_str = self.connection_string.resolve_value() or ""
384
+ try:
385
+ return Connection.connect(conn_str)
386
+ except Error as e:
387
+ msg = (
388
+ "Failed to connect to PostgreSQL database. Ensure the connection string follows the "
389
+ "PostgreSQL connection specification: "
390
+ "https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING."
391
+ )
392
+ raise DocumentStoreError(msg) from e
393
+
394
+ async def _create_connection_async(self) -> AsyncConnection:
395
+ """
396
+ Opens a new async connection to the PostgreSQL database.
397
+
398
+ Async counterpart of `_create_connection`, overridable in the same way. Everything else is handled by
399
+ `_ensure_db_setup_async`.
400
+
401
+ :raises DocumentStoreError: If the connection cannot be opened.
402
+ """
403
+ conn_str = self.connection_string.resolve_value() or ""
404
+ try:
405
+ return await AsyncConnection.connect(conn_str)
406
+ except Error as e:
407
+ msg = (
408
+ "Failed to connect to PostgreSQL database. Ensure the connection string follows the "
409
+ "PostgreSQL connection specification: "
410
+ "https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING."
411
+ )
412
+ raise DocumentStoreError(msg) from e
413
+
373
414
  def _ensure_db_setup(self) -> None:
374
415
  """
375
416
  Ensures that the connection to the PostgreSQL database exists and is valid.
@@ -387,16 +428,7 @@ class PgvectorDocumentStore:
387
428
  except Error as e:
388
429
  logger.debug("Failed to close connection: {e}", e=str(e))
389
430
 
390
- conn_str = self.connection_string.resolve_value() or ""
391
- try:
392
- connection = Connection.connect(conn_str)
393
- except Error as e:
394
- msg = (
395
- "Failed to connect to PostgreSQL database. Ensure the connection string follows the "
396
- "PostgreSQL connection specification: "
397
- "https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING."
398
- )
399
- raise DocumentStoreError(msg) from e
431
+ connection = self._create_connection()
400
432
  connection.autocommit = True
401
433
  if self.create_extension:
402
434
  connection.execute("CREATE EXTENSION IF NOT EXISTS vector")
@@ -430,16 +462,7 @@ class PgvectorDocumentStore:
430
462
  if self._async_connection:
431
463
  await self._async_connection.close()
432
464
 
433
- conn_str = self.connection_string.resolve_value() or ""
434
- try:
435
- async_connection = await AsyncConnection.connect(conn_str)
436
- except Error as e:
437
- msg = (
438
- "Failed to connect to PostgreSQL database. Ensure the connection string follows the "
439
- "PostgreSQL connection specification: "
440
- "https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING."
441
- )
442
- raise DocumentStoreError(msg) from e
465
+ async_connection = await self._create_connection_async()
443
466
  await async_connection.set_autocommit(True)
444
467
  if self.create_extension:
445
468
  await async_connection.execute("CREATE EXTENSION IF NOT EXISTS vector")
@@ -448,6 +448,27 @@ def test_close_is_exception_safe(mock_store):
448
448
  assert mock_store._connection is None
449
449
 
450
450
 
451
+ @pytest.mark.usefixtures("patches_for_unit_tests")
452
+ def test_ensure_db_setup_uses_overridden_create_connection(monkeypatch):
453
+ monkeypatch.setenv("PG_CONN_STR", "some-connection-string")
454
+ mock_connection = Mock(spec=Connection)
455
+
456
+ class CustomConnectionDocumentStore(PgvectorDocumentStore):
457
+ def _create_connection(self) -> Connection:
458
+ return mock_connection
459
+
460
+ store = CustomConnectionDocumentStore()
461
+ with patch.object(CustomConnectionDocumentStore, "_initialize_table") as mock_initialize_table:
462
+ store._ensure_db_setup()
463
+
464
+ assert store._connection is mock_connection
465
+ assert mock_connection.autocommit is True
466
+ mock_connection.execute.assert_called_once_with("CREATE EXTENSION IF NOT EXISTS vector")
467
+ assert store._cursor is not None
468
+ assert store._dict_cursor is not None
469
+ mock_initialize_table.assert_called_once()
470
+
471
+
451
472
  @pytest.mark.integration
452
473
  def test_halfvec_hnsw_write_documents(document_store_w_halfvec_hnsw_index: PgvectorDocumentStore):
453
474
  documents = [
@@ -409,3 +409,30 @@ async def test_close_async_is_exception_safe(mock_store):
409
409
  await mock_store.close_async()
410
410
 
411
411
  assert mock_store._async_connection is None
412
+
413
+
414
+ @pytest.mark.asyncio
415
+ async def test_ensure_db_setup_async_uses_overridden_create_connection_async(monkeypatch):
416
+ monkeypatch.setenv("PG_CONN_STR", "some-connection-string")
417
+ mock_connection = Mock(spec=AsyncConnection)
418
+ mock_connection.set_autocommit = AsyncMock()
419
+ mock_connection.execute = AsyncMock()
420
+
421
+ class CustomConnectionDocumentStore(PgvectorDocumentStore):
422
+ async def _create_connection_async(self) -> AsyncConnection:
423
+ return mock_connection
424
+
425
+ store = CustomConnectionDocumentStore()
426
+ with (
427
+ patch("haystack_integrations.document_stores.pgvector.document_store.register_vector_async") as mock_register,
428
+ patch.object(CustomConnectionDocumentStore, "_initialize_table_async") as mock_initialize_table,
429
+ ):
430
+ await store._ensure_db_setup_async()
431
+
432
+ assert store._async_connection is mock_connection
433
+ mock_connection.set_autocommit.assert_awaited_once_with(True)
434
+ mock_connection.execute.assert_awaited_once_with("CREATE EXTENSION IF NOT EXISTS vector")
435
+ mock_register.assert_awaited_once_with(mock_connection)
436
+ assert store._async_cursor is not None
437
+ assert store._async_dict_cursor is not None
438
+ mock_initialize_table.assert_awaited_once()