typesense: 29.0 -> 30.2; python3Packages.typesense: 1.3.0 -> 2.0.0 (#503394)

This commit is contained in:
Peder Bergebakken Sundt
2026-09-22 17:17:09 +00:00
committed by GitHub
9 changed files with 847 additions and 79 deletions

View File

@@ -1,17 +1,17 @@
{
"version": "29.0",
"version": "30.2",
"platforms": {
"aarch64-linux": {
"arch": "linux-arm64",
"hash": "sha256-ztjCyK2378tg9yT9D6ProINlMT5GyUIEH8duHivCQ2E="
"hash": "sha256-qbnW4pJ8hjkAMGKQ6FMsF/Zr3/NO8q0EOyTtTM7Iprw="
},
"x86_64-linux": {
"arch": "linux-amd64",
"hash": "sha256-BD0qE1dEVKVUPwO2fMO0SMXiwG9dD0RMnAzkVZitFKA="
"hash": "sha256-zXkWBefGzHvkV3lPU0zUufnTYXga2xDkACDvwihA68M="
},
"aarch64-darwin": {
"arch": "darwin-arm64",
"hash": "sha256-yAOR/bGYBQGp8Mllhh0yKyqmItd2+IfLib3W+lIHwr0="
"hash": "sha256-fY1tDDOTCtIOoj3RhCUFR7FmFZRL6JGyB46KB1FS+n4="
}
}
}

View File

@@ -0,0 +1,62 @@
From 24cb4ac0fcc6bfa88432c5c6a1b061f601458baf Mon Sep 17 00:00:00 2001
From: phanirithvij <phanirithvij2000@gmail.com>
Date: Wed, 25 Mar 2026 18:30:32 +0530
Subject: [PATCH 1/6] linux only metrics
Signed-off-by: phanirithvij <phanirithvij2000@gmail.com>
---
tests/metrics_test.py | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/tests/metrics_test.py b/tests/metrics_test.py
index 12fc300..6f2295d 100644
--- a/tests/metrics_test.py
+++ b/tests/metrics_test.py
@@ -42,18 +42,22 @@ def test_init_async(fake_async_api_call: AsyncApiCall) -> None:
)
assert metrics.resource_path == "/metrics.json" # noqa: WPS437
+import platform
+
def test_actual_retrieve(actual_metrics: Metrics) -> None:
"""Test that the Metrics object can retrieve metrics on Typesense server and verify response structure."""
response = actual_metrics.retrieve()
- assert "system_cpu_active_percentage" in response
+ if platform.system() == "Linux":
+ assert "system_cpu_active_percentage" in response
+ assert "system_network_received_bytes" in response
+ assert "system_network_sent_bytes" in response
+
assert "system_disk_total_bytes" in response
assert "system_disk_used_bytes" in response
assert "system_memory_total_bytes" in response
assert "system_memory_used_bytes" in response
- assert "system_network_received_bytes" in response
- assert "system_network_sent_bytes" in response
assert "typesense_memory_active_bytes" in response
assert "typesense_memory_allocated_bytes" in response
assert "typesense_memory_fragmentation_ratio" in response
@@ -68,13 +72,15 @@ async def test_actual_retrieve_async(actual_async_metrics: AsyncMetrics) -> None
"""Test that the AsyncMetrics object can retrieve metrics on Typesense server and verify response structure."""
response = await actual_async_metrics.retrieve()
- assert "system_cpu_active_percentage" in response
+ if platform.system() == "Linux":
+ assert "system_cpu_active_percentage" in response
+ assert "system_network_received_bytes" in response
+ assert "system_network_sent_bytes" in response
+
assert "system_disk_total_bytes" in response
assert "system_disk_used_bytes" in response
assert "system_memory_total_bytes" in response
assert "system_memory_used_bytes" in response
- assert "system_network_received_bytes" in response
- assert "system_network_sent_bytes" in response
assert "typesense_memory_active_bytes" in response
assert "typesense_memory_allocated_bytes" in response
assert "typesense_memory_fragmentation_ratio" in response
--
2.53.0

View File

@@ -1,11 +1,21 @@
From ed2f6f31f74fae21cb00b6ea3da92b300fadce76 Mon Sep 17 00:00:00 2001
From: phanirithvij <phanirithvij2000@gmail.com>
Date: Wed, 25 Mar 2026 19:05:02 +0530
Subject: [PATCH 2/6] generated temp path
Signed-off-by: phanirithvij <phanirithvij2000@gmail.com>
---
tests/operations_test.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/operations_test.py b/tests/operations_test.py
index 34bb74c..39f9265 100644
index b48b946..71c134e 100644
--- a/tests/operations_test.py
+++ b/tests/operations_test.py
@@ -51,11 +51,11 @@ def test_cache_clear(actual_operations: Operations) -> None:
@@ -69,11 +69,11 @@ def test_cache_clear(actual_operations: Operations) -> None:
assert response["success"]
-def test_snapshot(actual_operations: Operations) -> None:
+def test_snapshot(actual_operations: Operations, tmp_path) -> None:
"""Test that the Operations object can perform the snapshot operation."""
@@ -14,5 +24,8 @@ index 34bb74c..39f9265 100644
- {"snapshot_path": "/tmp"}, # noqa: S108
+ {"snapshot_path": str(tmp_path)}, # noqa: S108
)
assert response["success"]
--
2.53.0

View File

@@ -0,0 +1,106 @@
From 90047673e4191ffaa6431059f9a8c1ffb31ea3cb Mon Sep 17 00:00:00 2001
From: phanirithvij <phanirithvij2000@gmail.com>
Date: Wed, 25 Mar 2026 19:02:46 +0530
Subject: [PATCH 3/6] tests fix endpoint path
_endpoint_path is not a function anymore
Signed-off-by: phanirithvij <phanirithvij2000@gmail.com>
---
tests/override_test.py | 4 ++--
tests/overrides_test.py | 4 ++--
tests/synonym_test.py | 4 ++--
tests/synonyms_test.py | 4 ++--
4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/tests/override_test.py b/tests/override_test.py
index 89526c7..47fc81b 100644
--- a/tests/override_test.py
+++ b/tests/override_test.py
@@ -47,7 +47,7 @@ def test_init(fake_api_call: ApiCall) -> None:
fake_api_call.config.nearest_node,
)
assert (
- override._endpoint_path() # noqa: WPS437
+ override._endpoint_path # noqa: WPS437
== "/collections/companies/overrides/company_override"
)
@@ -104,7 +104,7 @@ def test_init_async(fake_async_api_call: AsyncApiCall) -> None:
fake_async_api_call.config.nearest_node,
)
assert (
- override._endpoint_path() # noqa: WPS437
+ override._endpoint_path # noqa: WPS437
== "/collections/companies/overrides/company_override"
)
diff --git a/tests/overrides_test.py b/tests/overrides_test.py
index a9376b5..de4de73 100644
--- a/tests/overrides_test.py
+++ b/tests/overrides_test.py
@@ -61,7 +61,7 @@ def test_get_missing_override(fake_overrides: Overrides) -> None:
)
assert override.collection_name == "companies"
assert (
- override._endpoint_path() # noqa: WPS437
+ override._endpoint_path # noqa: WPS437
== "/collections/companies/overrides/company_override"
)
@@ -186,7 +186,7 @@ def test_get_missing_override_async(fake_async_overrides) -> None:
)
assert override.collection_name == "companies"
assert (
- override._endpoint_path() # noqa: WPS437
+ override._endpoint_path # noqa: WPS437
== "/collections/companies/overrides/company_override"
)
diff --git a/tests/synonym_test.py b/tests/synonym_test.py
index cfe6e51..d9affd9 100644
--- a/tests/synonym_test.py
+++ b/tests/synonym_test.py
@@ -45,7 +45,7 @@ def test_init(fake_api_call: ApiCall) -> None:
fake_api_call.config.nearest_node,
)
assert (
- synonym._endpoint_path() # noqa: WPS437
+ synonym._endpoint_path # noqa: WPS437
== "/collections/companies/synonyms/company_synonym"
)
@@ -99,7 +99,7 @@ def test_init_async(fake_async_api_call: AsyncApiCall) -> None:
fake_async_api_call.config.nearest_node,
)
assert (
- synonym._endpoint_path() # noqa: WPS437
+ synonym._endpoint_path # noqa: WPS437
== "/collections/companies/synonyms/company_synonym"
)
diff --git a/tests/synonyms_test.py b/tests/synonyms_test.py
index 3402493..afe8638 100644
--- a/tests/synonyms_test.py
+++ b/tests/synonyms_test.py
@@ -62,7 +62,7 @@ def test_get_missing_synonym(fake_synonyms: Synonyms) -> None:
)
assert synonym.collection_name == "companies"
assert (
- synonym._endpoint_path() # noqa: WPS437
+ synonym._endpoint_path # noqa: WPS437
== "/collections/companies/synonyms/company_synonym"
)
@@ -174,7 +174,7 @@ def test_get_missing_synonym_async(fake_async_synonyms) -> None:
)
assert synonym.collection_name == "companies"
assert (
- synonym._endpoint_path() # noqa: WPS437
+ synonym._endpoint_path # noqa: WPS437
== "/collections/companies/synonyms/company_synonym"
)
--
2.53.0

View File

@@ -0,0 +1,29 @@
From f6989c8e29fcb03bf76f1b143d116f081091fad1 Mon Sep 17 00:00:00 2001
From: phanirithvij <phanirithvij2000@gmail.com>
Date: Wed, 25 Mar 2026 19:35:38 +0530
Subject: [PATCH 4/6] tests fix rule_id
rule_id is not found for this class but rule_name exists with the
expected value
Signed-off-by: phanirithvij <phanirithvij2000@gmail.com>
---
tests/analytics_rules_v1_test.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/analytics_rules_v1_test.py b/tests/analytics_rules_v1_test.py
index d222d99..d1021d8 100644
--- a/tests/analytics_rules_v1_test.py
+++ b/tests/analytics_rules_v1_test.py
@@ -45,7 +45,7 @@ def test_get_missing_analytics_rule(fake_analytics_rules: AnalyticsRulesV1) -> N
"""Test that the AnalyticsRulesV1 object can get a missing analytics_rule."""
analytics_rule = fake_analytics_rules["company_analytics_rule"]
- assert analytics_rule.rule_id == "company_analytics_rule"
+ assert analytics_rule.rule_name == "company_analytics_rule"
assert_match_object(analytics_rule.api_call, fake_analytics_rules.api_call)
assert_object_lists_match(
analytics_rule.api_call.node_manager.nodes,
--
2.53.0

View File

@@ -0,0 +1,385 @@
From 6eecb90897548584b8907731abf981237e032997 Mon Sep 17 00:00:00 2001
From: Fanis Tharropoulos <ftharropoulos@gmail.com>
Date: Thu, 7 May 2026 18:59:56 +0300
Subject: [PATCH 5/6] test: gate v30 collection schema expectations
- keep v29.0 and earlier tests passing
---
tests/collection_test.py | 31 +++--
tests/collections_test.py | 242 +++++++++++++-------------------------
2 files changed, 106 insertions(+), 167 deletions(-)
diff --git a/tests/collection_test.py b/tests/collection_test.py
index 7eb29fa..30093d1 100644
--- a/tests/collection_test.py
+++ b/tests/collection_test.py
@@ -5,12 +5,24 @@ from tests.utils.object_assertions import (
assert_object_lists_match,
assert_to_contain_object,
)
+from tests.utils.version import is_v30_or_above
from typesense.sync.api_call import ApiCall
+from typesense.sync.client import Client
from typesense.sync.collection import Collection
from typesense.sync.collections import Collections
from typesense.types.collection import CollectionSchema
+is_v30_or_above_server = is_v30_or_above(
+ Client(
+ {
+ "api_key": "xyz",
+ "nodes": [{"host": "localhost", "port": 8108, "protocol": "http"}],
+ }
+ )
+)
+
+
def test_init(fake_api_call: ApiCall) -> None:
"""Test that the Collection object is initialized correctly."""
collection = Collection(fake_api_call, "companies")
@@ -52,7 +64,6 @@ def test_actual_retrieve(
"infix": False,
"stem": False,
"stem_dictionary": "",
- "truncate_len": 100,
"store": True,
},
{
@@ -66,7 +77,6 @@ def test_actual_retrieve(
"infix": False,
"stem": False,
"stem_dictionary": "",
- "truncate_len": 100,
"store": True,
},
],
@@ -74,9 +84,12 @@ def test_actual_retrieve(
"num_documents": 0,
"symbols_to_index": [],
"token_separators": [],
- "synonym_sets": [],
- "curation_sets": [],
}
+ if is_v30_or_above_server:
+ expected["synonym_sets"] = []
+ expected["curation_sets"] = []
+ expected["fields"][0]["truncate_len"] = 100
+ expected["fields"][1]["truncate_len"] = 100
response.pop("created_at")
@@ -93,10 +106,8 @@ def test_actual_update(
{"fields": [{"name": "num_locations", "type": "int32"}]},
)
- expected: CollectionSchema = {
- "fields": [
- {"name": "num_locations", "truncate_len": 100, "type": "int32"},
- ],
- }
+ expected_field = {"name": "num_locations", "type": "int32"}
+ if is_v30_or_above_server:
+ expected_field["truncate_len"] = 100
- assert_to_contain_object(response.get("fields")[0], expected.get("fields")[0])
+ assert_to_contain_object(response.get("fields")[0], expected_field)
diff --git a/tests/collections_test.py b/tests/collections_test.py
index 788e3dc..94e3c60 100644
--- a/tests/collections_test.py
+++ b/tests/collections_test.py
@@ -1,6 +1,5 @@
"""Tests for the Collections class."""
-
import sys
from typesense.async_.api_call import AsyncApiCall
@@ -13,11 +12,68 @@ else:
from tests.utils.object_assertions import assert_match_object, assert_object_lists_match
from typesense.sync.api_call import ApiCall
+from tests.utils.version import is_v30_or_above
from typesense.sync.collections import Collections
from typesense.async_.collections import AsyncCollections
+from typesense.sync.client import Client
from typesense.types.collection import CollectionSchema
+IS_V30_OR_ABOVE = is_v30_or_above(
+ Client(
+ {
+ "api_key": "xyz",
+ "nodes": [{"host": "localhost", "port": 8108, "protocol": "http"}],
+ }
+ )
+)
+
+
+def expected_collection_field(
+ name: str,
+ type_: str,
+ *,
+ sort: bool,
+) -> dict[str, typing.Any]:
+ field: dict[str, typing.Any] = {
+ "name": name,
+ "type": type_,
+ "facet": False,
+ "index": True,
+ "optional": False,
+ "locale": "",
+ "sort": sort,
+ "infix": False,
+ "stem": False,
+ "stem_dictionary": "",
+ "store": True,
+ }
+ if IS_V30_OR_ABOVE:
+ field["truncate_len"] = 100
+ return field
+
+
+def expected_collection_schema(
+ *,
+ default_sorting_field: str,
+ fields: typing.List[dict[str, typing.Any]],
+ name: str,
+) -> CollectionSchema:
+ expected: CollectionSchema = {
+ "default_sorting_field": default_sorting_field,
+ "enable_nested_fields": False,
+ "fields": fields,
+ "name": name,
+ "num_documents": 0,
+ "symbols_to_index": [],
+ "token_separators": [],
+ }
+ if IS_V30_OR_ABOVE:
+ expected["synonym_sets"] = []
+ expected["curation_sets"] = []
+ return expected
+
+
def test_init(fake_api_call: ApiCall) -> None:
"""Test that the Collections object is initialized correctly."""
collections = Collections(fake_api_call)
@@ -98,46 +154,14 @@ def test_get_existing_collection(fake_collections: Collections) -> None:
def test_actual_create(actual_collections: Collections, delete_all: None) -> None:
"""Test that the Collections object can create a collection on Typesense Server."""
- expected: CollectionSchema = {
- "default_sorting_field": "",
- "enable_nested_fields": False,
- "fields": [
- {
- "name": "company_name",
- "type": "string",
- "facet": False,
- "index": True,
- "optional": False,
- "locale": "",
- "sort": False,
- "infix": False,
- "stem": False,
- "stem_dictionary": "",
- "truncate_len": 100,
- "store": True,
- },
- {
- "name": "num_employees",
- "type": "int32",
- "facet": False,
- "index": True,
- "optional": False,
- "locale": "",
- "sort": False,
- "infix": False,
- "stem": False,
- "stem_dictionary": "",
- "truncate_len": 100,
- "store": True,
- },
+ expected = expected_collection_schema(
+ default_sorting_field="",
+ fields=[
+ expected_collection_field("company_name", "string", sort=False),
+ expected_collection_field("num_employees", "int32", sort=False),
],
- "name": "companies",
- "num_documents": 0,
- "symbols_to_index": [],
- "token_separators": [],
- "synonym_sets": [],
- "curation_sets": [],
- }
+ name="companies",
+ )
response = actual_collections.create(
{
@@ -170,46 +194,14 @@ def test_actual_retrieve(
response = actual_collections.retrieve()
expected: typing.List[CollectionSchema] = [
- {
- "default_sorting_field": "num_employees",
- "enable_nested_fields": False,
- "fields": [
- {
- "name": "company_name",
- "type": "string",
- "facet": False,
- "index": True,
- "optional": False,
- "locale": "",
- "sort": False,
- "infix": False,
- "stem": False,
- "stem_dictionary": "",
- "truncate_len": 100,
- "store": True,
- },
- {
- "name": "num_employees",
- "type": "int32",
- "facet": False,
- "index": True,
- "optional": False,
- "locale": "",
- "sort": True,
- "infix": False,
- "stem": False,
- "stem_dictionary": "",
- "truncate_len": 100,
- "store": True,
- },
+ expected_collection_schema(
+ default_sorting_field="num_employees",
+ fields=[
+ expected_collection_field("company_name", "string", sort=False),
+ expected_collection_field("num_employees", "int32", sort=True),
],
- "name": "companies",
- "num_documents": 0,
- "symbols_to_index": [],
- "token_separators": [],
- "synonym_sets": [],
- "curation_sets": [],
- },
+ name="companies",
+ ),
]
response[0].pop("created_at")
@@ -235,46 +227,14 @@ async def test_actual_create_async(
actual_async_collections: AsyncCollections, delete_all: None
) -> None:
"""Test that the Collections object can create a collection on Typesense Server."""
- expected: CollectionSchema = {
- "default_sorting_field": "",
- "enable_nested_fields": False,
- "fields": [
- {
- "name": "company_name",
- "type": "string",
- "facet": False,
- "index": True,
- "optional": False,
- "locale": "",
- "sort": False,
- "infix": False,
- "stem": False,
- "stem_dictionary": "",
- "truncate_len": 100,
- "store": True,
- },
- {
- "name": "num_employees",
- "type": "int32",
- "facet": False,
- "index": True,
- "optional": False,
- "locale": "",
- "sort": False,
- "infix": False,
- "stem": False,
- "stem_dictionary": "",
- "truncate_len": 100,
- "store": True,
- },
+ expected = expected_collection_schema(
+ default_sorting_field="",
+ fields=[
+ expected_collection_field("company_name", "string", sort=False),
+ expected_collection_field("num_employees", "int32", sort=False),
],
- "name": "companies",
- "num_documents": 0,
- "symbols_to_index": [],
- "token_separators": [],
- "synonym_sets": [],
- "curation_sets": [],
- }
+ name="companies",
+ )
response = await actual_async_collections.create(
{
@@ -307,46 +267,14 @@ async def test_actual_retrieve_async(
response = await actual_async_collections.retrieve()
expected: typing.List[CollectionSchema] = [
- {
- "default_sorting_field": "num_employees",
- "enable_nested_fields": False,
- "fields": [
- {
- "name": "company_name",
- "type": "string",
- "facet": False,
- "index": True,
- "optional": False,
- "locale": "",
- "sort": False,
- "infix": False,
- "stem": False,
- "stem_dictionary": "",
- "truncate_len": 100,
- "store": True,
- },
- {
- "name": "num_employees",
- "type": "int32",
- "facet": False,
- "index": True,
- "optional": False,
- "locale": "",
- "sort": True,
- "infix": False,
- "stem": False,
- "stem_dictionary": "",
- "truncate_len": 100,
- "store": True,
- },
+ expected_collection_schema(
+ default_sorting_field="num_employees",
+ fields=[
+ expected_collection_field("company_name", "string", sort=False),
+ expected_collection_field("num_employees", "int32", sort=True),
],
- "name": "companies",
- "num_documents": 0,
- "symbols_to_index": [],
- "token_separators": [],
- "synonym_sets": [],
- "curation_sets": [],
- },
+ name="companies",
+ ),
]
response[0].pop("created_at")
--
2.53.0

View File

@@ -0,0 +1,194 @@
From a5f8ce27a246a1c0a3dd5236cffa0afeaaf166b5 Mon Sep 17 00:00:00 2001
From: Fanis Tharropoulos <ftharropoulos@gmail.com>
Date: Thu, 7 May 2026 19:26:14 +0300
Subject: [PATCH 6/6] feat(curation): add types for `stem` and `synonyms` for
Typesense v30.2
---
src/typesense/types/curation_set.py | 56 ++++++++++++++++++++++++++---
tests/curation_set_test.py | 13 ++++++-
tests/curation_sets_test.py | 4 +++
3 files changed, 67 insertions(+), 6 deletions(-)
diff --git a/src/typesense/types/curation_set.py b/src/typesense/types/curation_set.py
index 6468166..f99a020 100644
--- a/src/typesense/types/curation_set.py
+++ b/src/typesense/types/curation_set.py
@@ -33,15 +33,36 @@ class CurationRuleTagsSchema(typing.TypedDict):
tags: typing.List[str]
-class CurationRuleQuerySchema(typing.TypedDict):
+class CurationRuleQueryBaseSchema(typing.TypedDict):
"""
- Schema for a curation rule using query and match.
+ Schema for the base of a curation rule using query and match.
"""
query: str
match: typing.Literal["exact", "contains"]
+class CurationRuleQueryCreateSchema(CurationRuleQueryBaseSchema):
+ """
+ Schema for creating a curation rule using query and match.
+ """
+
+ stem: typing.NotRequired[bool]
+ synonyms: typing.NotRequired[bool]
+
+
+class CurationRuleQuerySchema(CurationRuleQueryBaseSchema):
+ """
+ Schema for retrieving a curation rule using query and match.
+ """
+
+ stem: typing.NotRequired[
+ bool
+ ] # TODO: This is a bug in Typesense server upstream, so until 31.0 is
+ # released, this is staying as notrequired.
+ synonyms: typing.NotRequired[bool]
+
+
class CurationRuleFilterBySchema(typing.TypedDict):
"""
Schema for a curation rule using filter_by.
@@ -85,20 +106,45 @@ class CurationItemSchema(typing.TypedDict):
metadata: typing.NotRequired[typing.Dict[str, typing.Any]]
+class CurationItemUpsertSchema(typing.TypedDict):
+ """
+ Schema for creating or updating a single curation item.
+ """
+
+ id: str
+ rule: typing.Union[
+ CurationRuleTagsSchema,
+ CurationRuleQueryCreateSchema,
+ CurationRuleFilterBySchema,
+ ]
+ includes: typing.NotRequired[typing.List[CurationIncludeSchema]]
+ excludes: typing.NotRequired[typing.List[CurationExcludeSchema]]
+ filter_by: typing.NotRequired[str]
+ sort_by: typing.NotRequired[str]
+ replace_query: typing.NotRequired[str]
+ remove_matched_tokens: typing.NotRequired[bool]
+ filter_curated_hits: typing.NotRequired[bool]
+ stop_processing: typing.NotRequired[bool]
+ effective_from_ts: typing.NotRequired[int]
+ effective_to_ts: typing.NotRequired[int]
+ metadata: typing.NotRequired[typing.Dict[str, typing.Any]]
+
+
class CurationSetUpsertSchema(typing.TypedDict):
"""
Payload schema to create or replace a curation set.
"""
- items: typing.List[CurationItemSchema]
+ items: typing.List[CurationItemUpsertSchema]
-class CurationSetSchema(CurationSetUpsertSchema, total=False):
+class CurationSetSchema(typing.TypedDict):
"""
Response schema for a curation set.
"""
- name: typing.NotRequired[str]
+ items: typing.List[CurationItemSchema]
+ name: str
class CurationSetsListEntrySchema(typing.TypedDict):
diff --git a/tests/curation_set_test.py b/tests/curation_set_test.py
index a75196a..fe07278 100644
--- a/tests/curation_set_test.py
+++ b/tests/curation_set_test.py
@@ -1,6 +1,5 @@
"""Tests for the CurationSet class including items APIs."""
-
import pytest
from tests.utils.version import is_v30_or_above
@@ -62,6 +61,8 @@ def test_actual_retrieve(
"rule": {
"match": "contains",
"query": "shoe",
+ "stem": False,
+ "synonyms": False,
},
"stop_processing": True,
},
@@ -108,6 +109,8 @@ def test_actual_list_items(
"rule": {
"match": "contains",
"query": "shoe",
+ "stem": False,
+ "synonyms": False,
},
"stop_processing": True,
},
@@ -140,6 +143,8 @@ def test_actual_get_item(
"rule": {
"match": "contains",
"query": "shoe",
+ "stem": False,
+ "synonyms": False,
},
"stop_processing": True,
}
@@ -218,6 +223,8 @@ async def test_actual_retrieve_async(
"rule": {
"match": "contains",
"query": "shoe",
+ "stem": False,
+ "synonyms": False,
},
"stop_processing": True,
},
@@ -263,6 +270,8 @@ async def test_actual_list_items_async(
"rule": {
"match": "contains",
"query": "shoe",
+ "stem": False,
+ "synonyms": False,
},
"stop_processing": True,
},
@@ -295,6 +304,8 @@ async def test_actual_get_item_async(
"rule": {
"match": "contains",
"query": "shoe",
+ "stem": False,
+ "synonyms": False,
},
"stop_processing": True,
}
diff --git a/tests/curation_sets_test.py b/tests/curation_sets_test.py
index 0a06a05..e4a635a 100644
--- a/tests/curation_sets_test.py
+++ b/tests/curation_sets_test.py
@@ -87,6 +87,8 @@ def test_actual_upsert(
"rule": {
"match": "contains",
"query": "shoe",
+ "stem": False,
+ "synonyms": False,
},
"stop_processing": True,
},
@@ -150,6 +152,8 @@ async def test_actual_upsert_async(
"rule": {
"match": "contains",
"query": "shoe",
+ "stem": False,
+ "synonyms": False,
},
"stop_processing": True,
},
--
2.53.0

View File

@@ -7,29 +7,38 @@
pytestCheckHook,
typesense,
curl,
pytest-mock,
requests-mock,
python-dotenv,
faker,
httpx,
isort,
pytest-asyncio,
pytest-httpx,
pytest-mock,
python-dotenv,
requests-mock,
respx,
}:
buildPythonPackage rec {
buildPythonPackage (finalAttrs: {
pname = "typesense";
version = "1.1.1";
version = "2.0.0";
pyproject = true;
src = fetchFromGitHub {
owner = "typesense";
repo = "typesense-python";
tag = "v${version}";
hash = "sha256-vo9DW4kinb00zWW4yX8ibyelQxW3eVabn+oMddPEd18=";
tag = "v${finalAttrs.version}";
hash = "sha256-GzapEl26FS6yMGeLC54y9ysl0mt9l6ceYHr84E6BqBo=";
};
patches = [
# See <https://github.com/typesense/typesense-python/pull/103>.
./linux-only-metrics.patch
./generated-temp-path.patch
# See <https://github.com/typesense/typesense-python/pull/132>.
# See <https://github.com/typesense/typesense-python/pull/133>.
./0001-linux-only-metrics.patch
./0002-generated-temp-path.patch
./0003-tests-fix-endpoint-path.patch
./0004-tests-fix-rule_id.patch
./0005-test-gate-v30-collection-schema-expectations.patch
./0006-feat-curation-add-types-for-stem-and-synonyms-for-Ty.patch
];
build-system = [ setuptools ];
@@ -40,31 +49,47 @@ buildPythonPackage rec {
pytestCheckHook
typesense
curl
pytest-mock
requests-mock
python-dotenv
faker
httpx
isort
pytest-asyncio
pytest-httpx
pytest-mock
python-dotenv
requests-mock
respx
];
disabledTestMarks = [ "open_ai" ];
disabledTests = [ "import_typing_extensions" ];
disabledTests = [
"import_typing_extensions"
# tests/operations_test.py::test_snapshot_async fails when tests are run
# in parallel due to writing to the shared /tmp directory on macOS
"test_snapshot_async"
];
__darwinAllowLocalNetworking = true;
# For darwin, the nix sandbox doesn't isolate loopback interfaces like linux does.
# So nixpkgs-review builds of python3.x will collide on the hardcoded port 8108.
# So for tests patch it to use random port.
preCheck = ''
export TYPESENSE_PORT=$(( 10000 + $$ % 30000 ))
export PEERING_PORT=$(( TYPESENSE_PORT - 1 ))
find tests -type f -exec sed -i "s/8108/$TYPESENSE_PORT/g" {} +
TYPESENSE_API_KEY="xyz" \
TYPESENSE_DATA_DIR="$(mktemp -d)" \
typesense-server &
typesense-server --api-port=$TYPESENSE_PORT --peering-port=$PEERING_PORT &
typesense_pid=$!
# Ensure typesense-server is killed even if tests fail
trap "kill $typesense_pid" EXIT
# Wait for typesense to finish starting.
timeout 20 bash -c '
while ! curl -s --fail localhost:8108/health; do sleep 1; done
' || false
'';
postCheck = ''
kill $typesense_pid
timeout 20 bash -c "
while ! curl -s --fail localhost:$TYPESENSE_PORT/health; do sleep 1; done
" || false
'';
pythonImportsCheck = [ "typesense" ];
@@ -74,5 +99,7 @@ buildPythonPackage rec {
homepage = "https://github.com/typesense/typesense-python";
license = lib.licenses.asl20;
teams = [ lib.teams.ngi ];
# on x86_64-darwin the typesense server doesn't start
badPlatforms = [ "x86_64-darwin" ];
};
}
})

View File

@@ -1,48 +0,0 @@
From 9f0024ae3a0377d15788256c72af7a692d250afc Mon Sep 17 00:00:00 2001
From: dotlambda <github@dotlambda.de>
Date: Thu, 23 Oct 2025 13:40:33 -0700
Subject: [PATCH] test(metrics): some metrics only exists on Linux
---
tests/metrics_test.py | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/tests/metrics_test.py b/tests/metrics_test.py
index 1e1ea47..fecf3c0 100644
--- a/tests/metrics_test.py
+++ b/tests/metrics_test.py
@@ -2,6 +2,8 @@
from __future__ import annotations
+import platform
+
from typesense.metrics import Metrics
@@ -9,13 +11,15 @@ def test_actual_retrieve(actual_metrics: Metrics) -> None:
"""Test that the Debug object can retrieve a debug on Typesense server and verify response structure."""
response = actual_metrics.retrieve()
- assert "system_cpu_active_percentage" in response
+ if platform.system() == "Linux":
+ assert "system_cpu_active_percentage" in response
+ assert "system_network_received_bytes" in response
+ assert "system_network_sent_bytes" in response
+
assert "system_disk_total_bytes" in response
assert "system_disk_used_bytes" in response
assert "system_memory_total_bytes" in response
assert "system_memory_used_bytes" in response
- assert "system_network_received_bytes" in response
- assert "system_network_sent_bytes" in response
assert "typesense_memory_active_bytes" in response
assert "typesense_memory_allocated_bytes" in response
assert "typesense_memory_fragmentation_ratio" in response
@@ -23,4 +27,4 @@ def test_actual_retrieve(actual_metrics: Metrics) -> None:
assert "typesense_memory_mapped_bytes" in response
assert "typesense_memory_metadata_bytes" in response
assert "typesense_memory_resident_bytes" in response
- assert "typesense_memory_retained_bytes" in response
\ No newline at end of file
+ assert "typesense_memory_retained_bytes" in response