Skip to content

Commit 348aeaf

Browse files
committed
Release: v6.0.0
- Added support for the new Composite Recommendation endpoint - Added new parameter `autoPresented` for Detail View and View Portion interactions - Added new parameter `timeSpent` for View Portion interactions - Added support for `reqlExpressions` on recommended items - Added support for input classes - Format code using `black`
1 parent fcd9b6a commit 348aeaf

File tree

226 files changed

+5987
-2390
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

226 files changed

+5987
-2390
lines changed

recombee_api_client/api_client.py

Lines changed: 60 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class Region(Enum):
1717
"""
1818
Region of the Recombee cluster
1919
"""
20+
2021
AP_SE = 1
2122
CA_EAST = 2
2223
EU_WEST = 3
@@ -28,16 +29,24 @@ class RecombeeClient:
2829
Client for sending requests to Recombee recommender system
2930
3031
:param database_id: Name of your database_id at Recombee
31-
32+
3233
:param token: Secret token obtained from Recombee for signing requests
33-
34+
3435
:param protocol: Default protocol for sending requests. Possible values: 'http', 'https'.
3536
3637
:param region: region of the Recombee cluster where the database is located
3738
"""
39+
3840
BATCH_MAX_SIZE = 10000
3941

40-
def __init__(self, database_id: str, token: str, protocol: str = 'https', options: dict = None, region: Region = None):
42+
def __init__(
43+
self,
44+
database_id: str,
45+
token: str,
46+
protocol: str = "https",
47+
options: dict = None,
48+
region: Region = None,
49+
):
4150
self.database_id = database_id
4251
self.token = token
4352
self.protocol = protocol
@@ -48,85 +57,91 @@ def send(self, request: Request) -> Union[dict, str, list]:
4857
"""
4958
:param request: Request to be sent to Recombee recommender
5059
"""
51-
60+
5261
if isinstance(request, Batch) and len(request.requests) > self.BATCH_MAX_SIZE:
5362
return self.__send_multipart_batch(request)
5463

5564
timeout = request.timeout / 1000
5665
uri = self.__process_request_uri(request)
5766
uri = self.__sign_url(uri)
58-
protocol = 'https' if request.ensure_https else self.protocol
59-
uri = protocol + '://' + self.base_uri + uri
67+
protocol = "https" if request.ensure_https else self.protocol
68+
uri = protocol + "://" + self.base_uri + uri
6069
try:
61-
if request.method == 'put':
70+
if request.method == "put":
6271
return self.__put(request, uri, timeout)
63-
elif request.method == 'get':
72+
elif request.method == "get":
6473
return self.__get(request, uri, timeout)
65-
elif request.method == 'post':
74+
elif request.method == "post":
6675
return self.__post(request, uri, timeout)
67-
elif request.method == 'delete':
76+
elif request.method == "delete":
6877
return self.__delete(request, uri, timeout)
6978
except requests.exceptions.Timeout:
7079
raise ApiTimeoutException(request)
7180

7281
@staticmethod
7382
def __get_regional_base_uri(region: Region) -> str:
7483
uri = {
75-
Region.AP_SE: 'rapi-ap-se.recombee.com',
76-
Region.CA_EAST: 'rapi-ca-east.recombee.com',
77-
Region.EU_WEST: 'rapi-eu-west.recombee.com',
78-
Region.US_WEST: 'rapi-us-west.recombee.com'
79-
}.get(region)
84+
Region.AP_SE: "rapi-ap-se.recombee.com",
85+
Region.CA_EAST: "rapi-ca-east.recombee.com",
86+
Region.EU_WEST: "rapi-eu-west.recombee.com",
87+
Region.US_WEST: "rapi-us-west.recombee.com",
88+
}.get(region)
8089

8190
if uri is None:
82-
raise ValueError('Unknown region given')
91+
raise ValueError("Unknown region given")
8392
return uri
8493

8594
@staticmethod
8695
def __get_base_uri(options: dict, region: str) -> str:
87-
base_uri = os.environ.get('RAPI_URI') or options.get('base_uri')
96+
base_uri = os.environ.get("RAPI_URI") or options.get("base_uri")
8897
if region is not None:
8998
if base_uri:
90-
raise ValueError('base_uri and region cannot be specified at the same time')
99+
raise ValueError(
100+
"base_uri and region cannot be specified at the same time"
101+
)
91102
base_uri = RecombeeClient.__get_regional_base_uri(region)
92103

93-
return base_uri or 'rapi.recombee.com'
104+
return base_uri or "rapi.recombee.com"
94105

95106
@staticmethod
96107
def __get_http_headers(additional_headers: dict = None) -> dict:
97-
headers = {'User-Agent': 'recombee-python-api-client/5.1.0'}
108+
headers = {"User-Agent": "recombee-python-api-client/6.0.0"}
98109
if additional_headers:
99110
headers.update(additional_headers)
100111
return headers
101112

102113
def __put(self, request: Request, uri: str, timeout: int):
103-
response = requests.put(uri,
104-
data=json.dumps(request.get_body_parameters()),
105-
headers=self.__get_http_headers({'Content-Type': 'application/json'}),
106-
timeout=timeout)
114+
response = requests.put(
115+
uri,
116+
data=json.dumps(request.get_body_parameters()),
117+
headers=self.__get_http_headers({"Content-Type": "application/json"}),
118+
timeout=timeout,
119+
)
107120
self.__check_errors(response, request)
108121
return response.json()
109122

110123
def __get(self, request: Request, uri: str, timeout: int):
111-
response = requests.get(uri,
112-
headers=self.__get_http_headers(),
113-
timeout=timeout)
124+
response = requests.get(uri, headers=self.__get_http_headers(), timeout=timeout)
114125
self.__check_errors(response, request)
115126
return response.json()
116127

117128
def __post(self, request: Request, uri: str, timeout: int):
118-
response = requests.post(uri,
119-
data=json.dumps(request.get_body_parameters()),
120-
headers=self.__get_http_headers({'Content-Type': 'application/json'}),
121-
timeout=timeout)
129+
response = requests.post(
130+
uri,
131+
data=json.dumps(request.get_body_parameters()),
132+
headers=self.__get_http_headers({"Content-Type": "application/json"}),
133+
timeout=timeout,
134+
)
122135
self.__check_errors(response, request)
123136
return response.json()
124137

125138
def __delete(self, request: Request, uri: str, timeout: int):
126-
response = requests.delete(uri,
127-
data=json.dumps(request.get_body_parameters()),
128-
headers=self.__get_http_headers({'Content-Type': 'application/json'}),
129-
timeout=timeout)
139+
response = requests.delete(
140+
uri,
141+
data=json.dumps(request.get_body_parameters()),
142+
headers=self.__get_http_headers({"Content-Type": "application/json"}),
143+
timeout=timeout,
144+
)
130145
self.__check_errors(response, request)
131146
return response.json()
132147

@@ -141,10 +156,12 @@ def __get_list_chunks(l: list, n: int) -> list:
141156
"""Yield successive n-sized chunks from l."""
142157

143158
for i in range(0, len(l), n):
144-
yield l[i:i + n]
159+
yield l[i : i + n]
145160

146161
def __send_multipart_batch(self, batch: Batch) -> list:
147-
requests_parts = [rqs for rqs in self.__get_list_chunks(batch.requests, self.BATCH_MAX_SIZE)]
162+
requests_parts = [
163+
rqs for rqs in self.__get_list_chunks(batch.requests, self.BATCH_MAX_SIZE)
164+
]
148165
responses = [self.send(Batch(rqs)) for rqs in requests_parts]
149166
return sum(responses, [])
150167

@@ -154,31 +171,31 @@ def __process_request_uri(self, request: Request) -> str:
154171
return uri
155172

156173
def __query_parameters_to_url(self, request: Request) -> str:
157-
ps = ''
174+
ps = ""
158175
query_params = request.get_query_parameters()
159176
for name in query_params:
160177
val = query_params[name]
161-
ps += '&' if ps.find('?') != -1 else '?'
178+
ps += "&" if ps.find("?") != -1 else "?"
162179
ps += "%s=%s" % (name, self.__format_query_parameter_value(val))
163180
return ps
164181

165182
@staticmethod
166183
def __format_query_parameter_value(value) -> str:
167184
if isinstance(value, list):
168-
return ','.join([quote(str(v)) for v in value])
185+
return ",".join([quote(str(v)) for v in value])
169186
return quote(str(value))
170187

171188
# Sign request with HMAC, request URI must be exactly the same
172189
# We have 30s to complete request with this token
173190
def __sign_url(self, req_part: str) -> str:
174-
uri = '/' + self.database_id + req_part
191+
uri = "/" + self.database_id + req_part
175192
time_part = self.__hmac_time(uri)
176193
sign = self.__hmac_sign(uri, time_part)
177-
res = uri + time_part + '&hmac_sign=' + sign
194+
res = uri + time_part + "&hmac_sign=" + sign
178195
return res
179196

180197
def __hmac_time(self, uri: str) -> str:
181-
res = '&' if uri.find('?') != -1 else '?'
198+
res = "&" if uri.find("?") != -1 else "?"
182199
res += "hmac_timestamp=%s" % int(time.time())
183200
return res
184201

recombee_api_client/api_requests/__init__.py

Lines changed: 69 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -39,40 +39,87 @@
3939
from recombee_api_client.api_requests.list_user_ratings import ListUserRatings
4040
from recombee_api_client.api_requests.add_cart_addition import AddCartAddition
4141
from recombee_api_client.api_requests.delete_cart_addition import DeleteCartAddition
42-
from recombee_api_client.api_requests.list_item_cart_additions import ListItemCartAdditions
43-
from recombee_api_client.api_requests.list_user_cart_additions import ListUserCartAdditions
42+
from recombee_api_client.api_requests.list_item_cart_additions import (
43+
ListItemCartAdditions,
44+
)
45+
from recombee_api_client.api_requests.list_user_cart_additions import (
46+
ListUserCartAdditions,
47+
)
4448
from recombee_api_client.api_requests.add_bookmark import AddBookmark
4549
from recombee_api_client.api_requests.delete_bookmark import DeleteBookmark
4650
from recombee_api_client.api_requests.list_item_bookmarks import ListItemBookmarks
4751
from recombee_api_client.api_requests.list_user_bookmarks import ListUserBookmarks
4852
from recombee_api_client.api_requests.set_view_portion import SetViewPortion
4953
from recombee_api_client.api_requests.delete_view_portion import DeleteViewPortion
50-
from recombee_api_client.api_requests.list_item_view_portions import ListItemViewPortions
51-
from recombee_api_client.api_requests.list_user_view_portions import ListUserViewPortions
52-
from recombee_api_client.api_requests.recommend_items_to_user import RecommendItemsToUser
53-
from recombee_api_client.api_requests.recommend_items_to_item import RecommendItemsToItem
54-
from recombee_api_client.api_requests.recommend_items_to_item_segment import RecommendItemsToItemSegment
54+
from recombee_api_client.api_requests.list_item_view_portions import (
55+
ListItemViewPortions,
56+
)
57+
from recombee_api_client.api_requests.list_user_view_portions import (
58+
ListUserViewPortions,
59+
)
60+
from recombee_api_client.api_requests.recommend_items_to_user import (
61+
RecommendItemsToUser,
62+
)
63+
from recombee_api_client.api_requests.recommend_items_to_item import (
64+
RecommendItemsToItem,
65+
)
66+
from recombee_api_client.api_requests.recommend_items_to_item_segment import (
67+
RecommendItemsToItemSegment,
68+
)
5569
from recombee_api_client.api_requests.recommend_next_items import RecommendNextItems
56-
from recombee_api_client.api_requests.recommend_users_to_user import RecommendUsersToUser
57-
from recombee_api_client.api_requests.recommend_users_to_item import RecommendUsersToItem
58-
from recombee_api_client.api_requests.recommend_item_segments_to_user import RecommendItemSegmentsToUser
59-
from recombee_api_client.api_requests.recommend_item_segments_to_item import RecommendItemSegmentsToItem
60-
from recombee_api_client.api_requests.recommend_item_segments_to_item_segment import RecommendItemSegmentsToItemSegment
70+
from recombee_api_client.api_requests.recommend_users_to_user import (
71+
RecommendUsersToUser,
72+
)
73+
from recombee_api_client.api_requests.recommend_users_to_item import (
74+
RecommendUsersToItem,
75+
)
76+
from recombee_api_client.api_requests.recommend_item_segments_to_user import (
77+
RecommendItemSegmentsToUser,
78+
)
79+
from recombee_api_client.api_requests.recommend_item_segments_to_item import (
80+
RecommendItemSegmentsToItem,
81+
)
82+
from recombee_api_client.api_requests.recommend_item_segments_to_item_segment import (
83+
RecommendItemSegmentsToItemSegment,
84+
)
85+
from recombee_api_client.api_requests.composite_recommendation import (
86+
CompositeRecommendation,
87+
)
6188
from recombee_api_client.api_requests.search_items import SearchItems
6289
from recombee_api_client.api_requests.search_item_segments import SearchItemSegments
6390
from recombee_api_client.api_requests.add_search_synonym import AddSearchSynonym
6491
from recombee_api_client.api_requests.list_search_synonyms import ListSearchSynonyms
65-
from recombee_api_client.api_requests.delete_all_search_synonyms import DeleteAllSearchSynonyms
92+
from recombee_api_client.api_requests.delete_all_search_synonyms import (
93+
DeleteAllSearchSynonyms,
94+
)
6695
from recombee_api_client.api_requests.delete_search_synonym import DeleteSearchSynonym
67-
from recombee_api_client.api_requests.create_property_based_segmentation import CreatePropertyBasedSegmentation
68-
from recombee_api_client.api_requests.update_property_based_segmentation import UpdatePropertyBasedSegmentation
69-
from recombee_api_client.api_requests.create_auto_reql_segmentation import CreateAutoReqlSegmentation
70-
from recombee_api_client.api_requests.update_auto_reql_segmentation import UpdateAutoReqlSegmentation
71-
from recombee_api_client.api_requests.create_manual_reql_segmentation import CreateManualReqlSegmentation
72-
from recombee_api_client.api_requests.update_manual_reql_segmentation import UpdateManualReqlSegmentation
73-
from recombee_api_client.api_requests.add_manual_reql_segment import AddManualReqlSegment
74-
from recombee_api_client.api_requests.update_manual_reql_segment import UpdateManualReqlSegment
75-
from recombee_api_client.api_requests.delete_manual_reql_segment import DeleteManualReqlSegment
96+
from recombee_api_client.api_requests.create_property_based_segmentation import (
97+
CreatePropertyBasedSegmentation,
98+
)
99+
from recombee_api_client.api_requests.update_property_based_segmentation import (
100+
UpdatePropertyBasedSegmentation,
101+
)
102+
from recombee_api_client.api_requests.create_auto_reql_segmentation import (
103+
CreateAutoReqlSegmentation,
104+
)
105+
from recombee_api_client.api_requests.update_auto_reql_segmentation import (
106+
UpdateAutoReqlSegmentation,
107+
)
108+
from recombee_api_client.api_requests.create_manual_reql_segmentation import (
109+
CreateManualReqlSegmentation,
110+
)
111+
from recombee_api_client.api_requests.update_manual_reql_segmentation import (
112+
UpdateManualReqlSegmentation,
113+
)
114+
from recombee_api_client.api_requests.add_manual_reql_segment import (
115+
AddManualReqlSegment,
116+
)
117+
from recombee_api_client.api_requests.update_manual_reql_segment import (
118+
UpdateManualReqlSegment,
119+
)
120+
from recombee_api_client.api_requests.delete_manual_reql_segment import (
121+
DeleteManualReqlSegment,
122+
)
76123
from recombee_api_client.api_requests.list_segmentations import ListSegmentations
77124
from recombee_api_client.api_requests.get_segmentation import GetSegmentation
78125
from recombee_api_client.api_requests.delete_segmentation import DeleteSegmentation

0 commit comments

Comments
 (0)