Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(recommendation): rename RecommendationClient to PersonalizationClient #536

Merged
merged 1 commit into from
Oct 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions algoliasearch/configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,19 @@ def build_hosts(self):
return HostsCollection(
[Host("{}.{}.{}".format("recommendation", self._region, "algolia.com"))]
)


class PersonalizationConfig(Config):
def __init__(self, app_id=None, api_key=None, region=None):
# type: (Optional[str], Optional[str], Optional[str]) -> None

self._region = "us" if region is None else region

super(PersonalizationConfig, self).__init__(app_id, api_key)

def build_hosts(self):
# type: () -> HostsCollection

return HostsCollection(
[Host("{}.{}.{}".format("personalization", self._region, "algolia.com"))]
)
70 changes: 70 additions & 0 deletions algoliasearch/personalization_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
from typing import Optional, Union

from algoliasearch.configs import PersonalizationConfig
from algoliasearch.helpers import is_async_available
from algoliasearch.http.request_options import RequestOptions
from algoliasearch.http.requester import Requester
from algoliasearch.http.transporter import Transporter
from algoliasearch.http.verb import Verb


class PersonalizationClient(object):
def __init__(self, transporter, config):
# type: (Transporter, PersonalizationConfig) -> None

self._transporter = transporter
self._config = config

@staticmethod
def create(app_id=None, api_key=None, region=None):
# type: (Optional[str], Optional[str], Optional[str]) -> PersonalizationClient # noqa: E501

config = PersonalizationConfig(app_id, api_key, region)

return PersonalizationClient.create_with_config(config)

@staticmethod
def create_with_config(config):
# type: (PersonalizationConfig) -> PersonalizationClient

requester = Requester()
transporter = Transporter(requester, config)

client = PersonalizationClient(transporter, config)

if is_async_available():
from algoliasearch.personalization_client_async import (
PersonalizationClientAsync,
)
from algoliasearch.http.transporter_async import TransporterAsync
from algoliasearch.http.requester_async import RequesterAsync

return PersonalizationClientAsync(
client, TransporterAsync(RequesterAsync(), config), config
)

return client

def set_personalization_strategy(
self, personalization_strategy, request_options=None
): # noqa: E501
# type: (dict, Optional[Union[dict, RequestOptions]]) -> dict

return self._transporter.write(
Verb.POST,
"1/strategies/personalization",
personalization_strategy,
request_options,
)

def get_personalization_strategy(self, request_options=None):
# type: (Optional[Union[dict, RequestOptions]]) -> dict

return self._transporter.read(
Verb.GET, "1/strategies/personalization", None, request_options
)

def close(self):
# type: () -> None

return self._transporter.close() # type: ignore
43 changes: 43 additions & 0 deletions algoliasearch/personalization_client_async.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import types
import asyncio
from typing import Optional, Type

from algoliasearch.personalization_client import PersonalizationClient
from algoliasearch.configs import PersonalizationConfig
from algoliasearch.helpers_async import _create_async_methods_in
from algoliasearch.http.transporter_async import TransporterAsync


class PersonalizationClientAsync(PersonalizationClient):
def __init__(self, personalization_client, transporter, search_config):
# type: (PersonalizationClient, TransporterAsync, PersonalizationConfig) -> None # noqa: E501

self._transporter_async = transporter

super(PersonalizationClientAsync, self).__init__(
personalization_client._transporter, search_config
)

client = PersonalizationClient(transporter, search_config)

_create_async_methods_in(self, client)

@asyncio.coroutine
def __aenter__(self):
# type: () -> PersonalizationClientAsync # type: ignore

return self # type: ignore

@asyncio.coroutine
def __aexit__(self, exc_type, exc, tb): # type: ignore
# type: (Optional[Type[BaseException]], Optional[BaseException],Optional[types.TracebackType]) -> None # noqa: E501

yield from self.close_async() # type: ignore

@asyncio.coroutine
def close_async(self): # type: ignore
# type: () -> None

super().close()

yield from self._transporter_async.close() # type: ignore
54 changes: 53 additions & 1 deletion algoliasearch/recommendation_client.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import Optional, Union, Dict, Any
import warnings
from typing import Optional, Union

from algoliasearch.configs import RecommendationConfig
from algoliasearch.helpers import is_async_available
Expand All @@ -12,13 +13,25 @@ class RecommendationClient(object):
def __init__(self, transporter, config):
# type: (Transporter, RecommendationConfig) -> None

warnings.warn(
"`%s.%s` is deprecated, use `%s.%s` instead."
% ("RecommendationClient", "init", "PersonalizationClient", "init",),
DeprecationWarning,
)

self._transporter = transporter
self._config = config

@staticmethod
def create(app_id=None, api_key=None, region=None):
# type: (Optional[str], Optional[str], Optional[str]) -> RecommendationClient # noqa: E501

warnings.warn(
"`%s.%s` is deprecated, use `%s.%s` instead."
% ("RecommendationClient", "create", "PersonalizationClient", "create",),
DeprecationWarning,
)

config = RecommendationConfig(app_id, api_key, region)

return RecommendationClient.create_with_config(config)
Expand All @@ -27,6 +40,17 @@ def create(app_id=None, api_key=None, region=None):
def create_with_config(config):
# type: (RecommendationConfig) -> RecommendationClient

warnings.warn(
"`%s.%s` is deprecated, use `%s.%s` instead."
% (
"RecommendationClient",
"create_with_config",
"PersonalizationClient",
"create_with_config",
),
DeprecationWarning,
)

requester = Requester()
transporter = Transporter(requester, config)

Expand All @@ -50,6 +74,17 @@ def set_personalization_strategy(
): # noqa: E501
# type: (dict, Optional[Union[dict, RequestOptions]]) -> dict

warnings.warn(
"`%s.%s` is deprecated, use `%s.%s` instead."
% (
"RecommendationClient",
"set_personalization_strategy",
"PersonalizationClient",
"set_personalization_strategy",
),
DeprecationWarning,
)

return self._transporter.write(
Verb.POST,
"1/strategies/personalization",
Expand All @@ -60,11 +95,28 @@ def set_personalization_strategy(
def get_personalization_strategy(self, request_options=None):
# type: (Optional[Union[dict, RequestOptions]]) -> dict

warnings.warn(
"`%s.%s` is deprecated, use `%s.%s` instead."
% (
"RecommendationClient",
"get_personalization_strategy",
"PersonalizationClient",
"get_personalization_strategy",
),
DeprecationWarning,
)

return self._transporter.read(
Verb.GET, "1/strategies/personalization", None, request_options
)

def close(self):
# type: () -> None

warnings.warn(
"`%s.%s` is deprecated, use `%s.%s` instead."
% ("RecommendationClient", "close", "PersonalizationClient", "close",),
DeprecationWarning,
)

return self._transporter.close() # type: ignore
4 changes: 2 additions & 2 deletions algoliasearch/search_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ def set_personalization_strategy(self, strategy, request_options=None):
% (
"SearchClient",
"set_personalization_strategy",
"RecommendationClient",
"PersonalizationClient",
"set_personalization_strategy",
),
DeprecationWarning,
Expand All @@ -363,7 +363,7 @@ def get_personalization_strategy(self, request_options=None):
% (
"SearchClient",
"get_personalization_strategy",
"RecommendationClient",
"PersonalizationClient",
"get_personalization_strategy",
),
DeprecationWarning,
Expand Down
46 changes: 46 additions & 0 deletions tests/features/test_personalization_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import unittest

from tests.helpers.env import Env
from tests.helpers.factory import Factory as F
from algoliasearch.exceptions import RequestException


class TestPersonalizationClient(unittest.TestCase):
def setUp(self):
self.client = F.personalization_client()

def tearDown(self):
self.client.close()

@unittest.skipIf(
Env.is_community(), "Community can not test personalization operations"
)
def test_personalization(self):
personalization_strategy = {
"eventsScoring": [
{"eventName": "Add to cart", "eventType": "conversion", "score": 50},
{"eventName": "Purchase", "eventType": "conversion", "score": 100},
],
"facetsScoring": [
{"facetName": "brand", "score": 100},
{"facetName": "categories", "score": 10},
],
"personalizationImpact": 0,
}

try:
response = self.client.set_personalization_strategy(
personalization_strategy
)
self.assertEqual(
response,
{"status": 200, "message": "Strategy was successfully updated"},
)
except RequestException as err:
self.assertEqual(
err,
RequestException("Number of strategy saves exceeded for the day", 429),
) # noqa: E501

response = self.client.get_personalization_strategy()
self.assertEqual(response, personalization_strategy)
17 changes: 17 additions & 0 deletions tests/helpers/factory.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import warnings
import datetime
import os
import platform
Expand All @@ -11,6 +12,7 @@
from algoliasearch.insights_client import InsightsClient
from algoliasearch.search_client import SearchClient, SearchConfig
from algoliasearch.recommendation_client import RecommendationClient
from algoliasearch.personalization_client import PersonalizationClient
from algoliasearch.http.hosts import HostsCollection, Host
from faker import Faker

Expand Down Expand Up @@ -82,11 +84,26 @@ def analytics_client(app_id=None, api_key=None):
def recommendation_client(app_id=None, api_key=None):
# type: (Optional[str], Optional[str]) -> RecommendationClient

warnings.warn(
"`%s` is deprecated, use `%s` instead."
% ("RecommendationClient", "PersonalizationClient",),
DeprecationWarning,
)

app_id = app_id if app_id is not None else Factory.get_app_id()
api_key = api_key if api_key is not None else Factory.get_api_key()

return Factory.decide(RecommendationClient.create(app_id, api_key))

@staticmethod
def personalization_client(app_id=None, api_key=None):
# type: (Optional[str], Optional[str]) -> PersonalizationClient

app_id = app_id if app_id is not None else Factory.get_app_id()
api_key = api_key if api_key is not None else Factory.get_api_key()

return Factory.decide(PersonalizationClient.create(app_id, api_key))

@staticmethod
def insights_client(app_id=None, api_key=None):
# type: (Optional[str], Optional[str]) -> InsightsClient
Expand Down