Skip to content

Commit 3109f95

Browse files
authored
Merge pull request #107 from tharropoulos/master
feat: add deprecation warning system for v30+ api migrations & add curation sets to client
2 parents 4c90850 + eb147fc commit 3109f95

20 files changed

+221
-110
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ classifiers = [
1616
"Programming Language :: Python",
1717
"Programming Language :: Python :: 3",
1818
]
19-
dependencies = ["requests"]
19+
dependencies = ["requests", "typing-extensions"]
2020
dynamic = ["version"]
2121

2222
[project.urls]

src/typesense/analytics_rule_v1.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,20 @@
2727
else:
2828
import typing_extensions as typing
2929

30+
from typing_extensions import deprecated
31+
3032
from typesense.api_call import ApiCall
33+
from typesense.logger import warn_deprecation
3134
from typesense.types.analytics_rule_v1 import (
3235
RuleDeleteSchema,
3336
RuleSchemaForCounters,
3437
RuleSchemaForQueries,
3538
)
3639

3740

41+
@deprecated(
42+
"AnalyticsRuleV1 is deprecated on v30+. Use client.analytics.rules[rule_id] instead."
43+
)
3844
class AnalyticsRuleV1:
3945
"""
4046
Class for managing individual analytics rules in Typesense (V1).
@@ -47,6 +53,10 @@ class AnalyticsRuleV1:
4753
rule_id (str): The ID of the analytics rule.
4854
"""
4955

56+
@warn_deprecation( # type: ignore[misc]
57+
"AnalyticsRuleV1 is deprecated on v30+. Use client.analytics.rules[rule_id] instead.",
58+
flag_name="analytics_rules_v1_deprecation",
59+
)
5060
def __init__(self, api_call: ApiCall, rule_id: str):
5161
"""
5262
Initialize the AnalyticsRuleV1 object.
@@ -102,5 +112,3 @@ def _endpoint_path(self) -> str:
102112
from typesense.analytics_rules_v1 import AnalyticsRulesV1
103113

104114
return "/".join([AnalyticsRulesV1.resource_path, self.rule_id])
105-
106-

src/typesense/analytics_rules_v1.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727

2828
import sys
2929

30+
from typesense.logger import warn_deprecation
31+
3032
if sys.version_info >= (3, 11):
3133
import typing
3234
else:
@@ -63,6 +65,10 @@ class AnalyticsRulesV1(object):
6365

6466
resource_path: typing.Final[str] = "/analytics/rules"
6567

68+
@warn_deprecation( # type: ignore[misc]
69+
"AnalyticsRulesV1 is deprecated on v30+. Use client.analytics instead.",
70+
flag_name="analytics_rules_v1_deprecation",
71+
)
6672
def __init__(self, api_call: ApiCall):
6773
"""
6874
Initialize the AnalyticsRulesV1 object.
@@ -161,5 +167,3 @@ def retrieve(self) -> RulesRetrieveSchema:
161167
entity_type=RulesRetrieveSchema,
162168
)
163169
return response
164-
165-

src/typesense/analytics_v1.py

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@
1717
versions through the use of the typing_extensions library.
1818
"""
1919

20+
from typing_extensions import deprecated
21+
2022
from typesense.analytics_rules_v1 import AnalyticsRulesV1
2123
from typesense.api_call import ApiCall
22-
from typesense.logger import logger
23-
24-
_analytics_v1_deprecation_warned = False
2524

2625

26+
@deprecated("AnalyticsV1 is deprecated on v30+. Use client.analytics instead.")
2727
class AnalyticsV1(object):
2828
"""
2929
Class for managing analytics in Typesense (V1).
@@ -46,13 +46,6 @@ def __init__(self, api_call: ApiCall) -> None:
4646

4747
@property
4848
def rules(self) -> AnalyticsRulesV1:
49-
global _analytics_v1_deprecation_warned
50-
if not _analytics_v1_deprecation_warned:
51-
logger.warning(
52-
"AnalyticsV1 is deprecated and will be removed in a future release. "
53-
"Use client.analytics instead."
54-
)
55-
_analytics_v1_deprecation_warned = True
5649
return self._rules
5750

5851

src/typesense/client.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828

2929
import sys
3030

31+
from typing_extensions import deprecated
32+
3133
from typesense.types.document import DocumentSchema
3234

3335
if sys.version_info >= (3, 11):
@@ -36,13 +38,14 @@
3638
import typing_extensions as typing
3739

3840
from typesense.aliases import Aliases
39-
from typesense.analytics_v1 import AnalyticsV1
4041
from typesense.analytics import Analytics
42+
from typesense.analytics_v1 import AnalyticsV1
4143
from typesense.api_call import ApiCall
4244
from typesense.collection import Collection
4345
from typesense.collections import Collections
4446
from typesense.configuration import ConfigDict, Configuration
4547
from typesense.conversations_models import ConversationsModels
48+
from typesense.curation_sets import CurationSets
4649
from typesense.debug import Debug
4750
from typesense.keys import Keys
4851
from typesense.metrics import Metrics
@@ -73,7 +76,8 @@ class Client:
7376
keys (Keys): Instance for managing API keys.
7477
aliases (Aliases): Instance for managing collection aliases.
7578
analyticsV1 (AnalyticsV1): Instance for analytics operations (V1).
76-
analytics (AnalyticsV30): Instance for analytics operations (v30).
79+
analytics (Analytics): Instance for analytics operations (v30).
80+
curation_sets (CurationSets): Instance for Curation Sets (v30+)
7781
stemming (Stemming): Instance for stemming dictionary operations.
7882
operations (Operations): Instance for various Typesense operations.
7983
debug (Debug): Instance for debug operations.
@@ -93,8 +97,10 @@ def __init__(self, config_dict: ConfigDict) -> None:
9397
Example:
9498
>>> config = {
9599
... "api_key": "your_api_key",
96-
... "nodes": [{"host": "localhost", "port": "8108", "protocol": "http"}],
97-
... "connection_timeout_seconds": 2
100+
... "nodes": [
101+
... {"host": "localhost", "port": "8108", "protocol": "http"}
102+
... ],
103+
... "connection_timeout_seconds": 2,
98104
... }
99105
>>> client = Client(config)
100106
"""
@@ -104,9 +110,10 @@ def __init__(self, config_dict: ConfigDict) -> None:
104110
self.multi_search = MultiSearch(self.api_call)
105111
self.keys = Keys(self.api_call)
106112
self.aliases = Aliases(self.api_call)
107-
self.analyticsV1 = AnalyticsV1(self.api_call)
113+
self._analyticsV1 = AnalyticsV1(self.api_call)
108114
self.analytics = Analytics(self.api_call)
109115
self.stemming = Stemming(self.api_call)
116+
self.curation_sets = CurationSets(self.api_call)
110117
self.operations = Operations(self.api_call)
111118
self.debug = Debug(self.api_call)
112119
self.stopwords = Stopwords(self.api_call)
@@ -115,6 +122,14 @@ def __init__(self, config_dict: ConfigDict) -> None:
115122
self.conversations_models = ConversationsModels(self.api_call)
116123
self.nl_search_models = NLSearchModels(self.api_call)
117124

125+
@property
126+
@deprecated(
127+
"AnalyticsV1 is deprecated on v30+. Use client.analytics instead.",
128+
category=None,
129+
)
130+
def analyticsV1(self) -> AnalyticsV1:
131+
return self._analyticsV1
132+
118133
def typed_collection(
119134
self,
120135
*,
@@ -140,7 +155,6 @@ def typed_collection(
140155
>>> class Company(DocumentSchema):
141156
... name: str
142157
... num_employees: int
143-
...
144158
>>> client = Client(config)
145159
>>> companies_collection = client.typed_collection(model=Company)
146160
# This is equivalent to:

src/typesense/collection.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
import sys
2222

23+
from typing_extensions import deprecated
24+
2325
from typesense.types.collection import CollectionSchema, CollectionUpdateSchema
2426

2527
if sys.version_info >= (3, 11):
@@ -63,8 +65,24 @@ def __init__(self, api_call: ApiCall, name: str):
6365
self.name = name
6466
self.api_call = api_call
6567
self.documents: Documents[TDoc] = Documents(api_call, name)
66-
self.overrides = Overrides(api_call, name)
67-
self.synonyms = Synonyms(api_call, name)
68+
self._overrides = Overrides(api_call, name)
69+
self._synonyms = Synonyms(api_call, name)
70+
71+
@property
72+
@deprecated(
73+
"Synonyms is deprecated on v30+. Use client.synonym_sets instead.",
74+
category=None,
75+
)
76+
def synonyms(self) -> Synonyms:
77+
return self._synonyms
78+
79+
@property
80+
@deprecated(
81+
"Overrides is deprecated on v30+. Use client.curation_sets instead.",
82+
category=None,
83+
)
84+
def overrides(self) -> Overrides:
85+
return self._overrides
6886

6987
def retrieve(self) -> CollectionSchema:
7088
"""

src/typesense/configuration.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ class ConfigDict(typing.TypedDict):
8080
dictionaries or URLs that represent the read replica nodes.
8181
8282
connection_timeout_seconds (float): The connection timeout in seconds.
83+
84+
suppress_deprecation_warnings (bool): Whether to suppress deprecation warnings.
8385
"""
8486

8587
nodes: typing.List[typing.Union[str, NodeConfigDict]]
@@ -96,6 +98,7 @@ class ConfigDict(typing.TypedDict):
9698
typing.List[typing.Union[str, NodeConfigDict]]
9799
] # deprecated
98100
connection_timeout_seconds: typing.NotRequired[float]
101+
suppress_deprecation_warnings: typing.NotRequired[bool]
99102

100103

101104
class Node:
@@ -220,6 +223,7 @@ def __init__(
220223
)
221224
self.verify = config_dict.get("verify", True)
222225
self.additional_headers = config_dict.get("additional_headers", {})
226+
self.suppress_deprecation_warnings = config_dict.get("suppress_deprecation_warnings", False)
223227

224228
def _handle_nearest_node(
225229
self,
@@ -371,7 +375,7 @@ def show_deprecation_warnings(config_dict: ConfigDict) -> None:
371375
to check for deprecated fields.
372376
"""
373377
if config_dict.get("timeout_seconds"):
374-
logger.warn(
378+
logger.warning(
375379
" ".join(
376380
[
377381
"Deprecation warning: timeout_seconds is now renamed",
@@ -381,7 +385,7 @@ def show_deprecation_warnings(config_dict: ConfigDict) -> None:
381385
)
382386

383387
if config_dict.get("master_node"):
384-
logger.warn(
388+
logger.warning(
385389
" ".join(
386390
[
387391
"Deprecation warning: master_node is now consolidated",
@@ -391,7 +395,7 @@ def show_deprecation_warnings(config_dict: ConfigDict) -> None:
391395
)
392396

393397
if config_dict.get("read_replica_nodes"):
394-
logger.warn(
398+
logger.warning(
395399
" ".join(
396400
[
397401
"Deprecation warning: read_replica_nodes is now",

src/typesense/curation_set.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@
99

1010
from typesense.api_call import ApiCall
1111
from typesense.types.curation_set import (
12-
CurationSetSchema,
12+
CurationItemDeleteSchema,
13+
CurationItemSchema,
1314
CurationSetDeleteSchema,
1415
CurationSetListItemResponseSchema,
15-
CurationItemSchema,
16-
CurationItemDeleteSchema,
16+
CurationSetSchema,
17+
CurationSetUpsertSchema,
1718
)
1819

1920

@@ -43,6 +44,17 @@ def delete(self) -> CurationSetDeleteSchema:
4344
)
4445
return response
4546

47+
def upsert(
48+
self,
49+
payload: CurationSetUpsertSchema,
50+
) -> CurationSetSchema:
51+
response: CurationSetSchema = self.api_call.put(
52+
"/".join([self._endpoint_path]),
53+
body=payload,
54+
entity_type=CurationSetSchema,
55+
)
56+
return response
57+
4658
# Items sub-resource
4759
@property
4860
def _items_path(self) -> str:
@@ -92,5 +104,3 @@ def delete_item(self, item_id: str) -> CurationItemDeleteSchema:
92104
entity_type=CurationItemDeleteSchema,
93105
)
94106
return response
95-
96-

src/typesense/curation_sets.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@
1010
from typesense.api_call import ApiCall
1111
from typesense.curation_set import CurationSet
1212
from typesense.types.curation_set import (
13-
CurationSetSchema,
1413
CurationSetsListResponseSchema,
15-
CurationSetUpsertSchema,
1614
)
1715

1816

@@ -34,15 +32,3 @@ def __getitem__(self, curation_set_name: str) -> CurationSet:
3432
from typesense.curation_set import CurationSet as PerSet
3533

3634
return PerSet(self.api_call, curation_set_name)
37-
38-
def upsert(
39-
self,
40-
curation_set_name: str,
41-
payload: CurationSetUpsertSchema,
42-
) -> CurationSetSchema:
43-
response: CurationSetSchema = self.api_call.put(
44-
"/".join([CurationSets.resource_path, curation_set_name]),
45-
body=payload,
46-
entity_type=CurationSetSchema,
47-
)
48-
return response

0 commit comments

Comments
 (0)