mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-10-02 21:10:08 +00:00
typesense: 29.0 -> 30.2; python3Packages.typesense: 1.3.0 -> 2.0.0 (#503394)
This commit is contained in:
@@ -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="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" ];
|
||||
};
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user