| """PredictoinIO Python SDK |
| |
| The PredictoinIO Python SDK provides easy-to-use functions for integrating |
| Python applications with PredictionIO REST API services. |
| """ |
| |
| __author__ = "The PredictionIO Team" |
| __email__ = "help@tappingstone.com" |
| __copyright__ = "Copyright 2013, TappingStone, Inc." |
| __license__ = "Apache License, Version 2.0" |
| |
| __version__ = "0.3" |
| |
| |
| # import packages |
| import re |
| import httplib |
| import json |
| import urllib |
| |
| from predictionio.connection import Connection |
| from predictionio.connection import AsyncRequest |
| from predictionio.connection import AsyncResponse |
| from predictionio.connection import PredictionIOAPIError |
| |
| """Error exception defined for this API |
| |
| Should be handled by the user |
| """ |
| class ServerStatusError(PredictionIOAPIError): |
| "Error happened when tried to get status of the API server" |
| pass |
| |
| class UserNotCreatedError(PredictionIOAPIError): |
| "Error happened when tried to create user" |
| pass |
| |
| class UserNotFoundError(PredictionIOAPIError): |
| "Error happened when tried to get user" |
| pass |
| |
| class UserNotDeletedError(PredictionIOAPIError): |
| "Error happened when tried to delete user" |
| pass |
| |
| class ItemNotCreatedError(PredictionIOAPIError): |
| "Error happened when tried to create item" |
| pass |
| |
| class ItemNotFoundError(PredictionIOAPIError): |
| "Error happened when tried to get item" |
| pass |
| |
| class ItemNotDeletedError(PredictionIOAPIError): |
| "Error happened when tried to delete item" |
| pass |
| |
| class U2IActionNotCreatedError(PredictionIOAPIError): |
| "Error happened when tried to create user-to-item action" |
| pass |
| |
| class ItemRecNotFoundError(PredictionIOAPIError): |
| "Error happened when tried to get item recommendation" |
| pass |
| |
| class InvalidArgumentError(PredictionIOAPIError): |
| "Arguments are not valid" |
| pass |
| |
| |
| # map to API |
| LIKE_API = "like" |
| DISLIKE_API = "dislike" |
| VIEW_API = "view" |
| CONVERSION_API = "conversion" |
| RATE_API = "rate" |
| |
| class Client: |
| """PredictionIO client object. |
| |
| This is an object representing a PredictionIO's client. This object provides methods for making PredictionIO API requests. |
| |
| :param appkey: the App Key provided by PredictionIO. |
| :param threads: number of threads to handle PredictionIO API requests. Must be >= 1. |
| :param apiurl: the PredictionIO API URL path. |
| :param apiversion: the PredictionIO API version. (optional) (eg. "", or "/v1") |
| |
| |
| """ |
| def __init__(self, appkey, threads=1, apiurl="http://localhost:8000", apiversion = ""): |
| """Constructor of Client object. |
| |
| :param appkey: the appkey |
| :param threads: number of threads for handling requests |
| :param apiurl: the PredictionIO API URL path. |
| :param apiversion: the PredictionIO API version. (optional) (eg. "", or "/v1") |
| |
| """ |
| self.appkey = appkey |
| self.threads = threads |
| self.apiurl = apiurl |
| self.apiversion = apiversion |
| |
| # check connection type |
| https_pattern = r'^https://(.*)' |
| http_pattern = r'^http://(.*)' |
| m = re.match(https_pattern, apiurl) |
| self.https = True |
| if m is None: # not matching https |
| m = re.match(http_pattern, apiurl) |
| self.https = False |
| if m is None: # not matching http either |
| raise InvalidArgumentError("apiurl is not valid: %s" % apiurl) |
| self.host = m.group(1) |
| |
| self._connection = Connection(host=self.host, threads=self.threads, https=self.https) |
| |
| def close(self): |
| """Close this client and the connection. |
| |
| Call this method when you want to completely terminate the connection with PredictionIO. |
| It will wait for all pending requests to finish. |
| """ |
| self._connection.close() |
| |
| def get_status(self): |
| """Get the status of the PredictionIO API Server |
| |
| :returns: |
| status message. |
| |
| :raises: |
| ServerStatusError. |
| """ |
| path = "/" |
| request = AsyncRequest("GET", path) |
| request.set_rfunc(self._aget_status_resp) |
| self._connection.make_request(request) |
| result = self.aresp(request) |
| return result |
| |
| def _aget_status_resp(self, response): |
| if response.error is not None: |
| raise ServerStatusError("Exception happened: %s for request %s" % \ |
| (response.error, response.request)) |
| elif response.status != httplib.OK: |
| raise ServerStatusError("request: %s status: %s body: %s" % \ |
| (response.request, response.status, response.body)) |
| |
| #data = json.loads(response.body) # convert json string to dict |
| return response.body |
| |
| def acreate_user(self, uid, **params): |
| """Asynchronously create a user. |
| |
| :param uid: user id. type str or int. |
| :param params: keyword arguments for optional attributes. |
| For example, bday="1985-01-23", inactive="true". |
| |
| :returns: |
| AsyncRequest object. You should call the aresp() method using this AsyncRequest |
| object as argument to get the final result or status of this asynchronous request. |
| |
| """ |
| path = "%s/users.json" % self.apiversion |
| request = AsyncRequest("POST", path, appkey=self.appkey, uid=uid, **params) |
| request.set_rfunc(self._acreate_user_resp) |
| self._connection.make_request(request) |
| |
| return request |
| |
| def _acreate_user_resp(self, response): |
| """Private function to handle the AsyncResponse of the acreate_user request. |
| |
| :param response: AsyncResponse object. |
| |
| :returns: |
| None. |
| |
| :raises: |
| UserNotCreatedError. |
| |
| """ |
| if response.error is not None: |
| raise UserNotCreatedError("Exception happened: %s for request %s" % \ |
| (response.error, response.request)) |
| elif response.status != httplib.CREATED: |
| raise UserNotCreatedError("request: %s status: %s body: %s" % \ |
| (response.request, response.status, response.body)) |
| |
| return None |
| |
| def aget_user(self, uid): |
| """Asynchronously get user. |
| |
| :param uid: user id. type str or int. |
| |
| :returns: |
| AsyncRequest object. You should call the aresp() method using this AsyncRequest |
| object as argument to get the final result or status of this asynchronous request. |
| """ |
| if type(uid) is int: |
| enc_uid = uid |
| else: |
| enc_uid = urllib.quote(uid,"") # replace special char with %xx |
| path = "%s/users/%s.json" % (self.apiversion, enc_uid) |
| request = AsyncRequest("GET", path, appkey=self.appkey) |
| request.set_rfunc(self._aget_user_resp) |
| self._connection.make_request(request) |
| |
| return request |
| |
| def _aget_user_resp(self, response): |
| """Private function to handle the AsyncResponse of the aget_user request . |
| |
| :param response: AsyncResponse object. |
| |
| :returns: |
| User data in Dictionary format. |
| |
| :rasies: |
| UserNotFoundError. |
| |
| """ |
| if response.error is not None: |
| raise UserNotFoundError("Exception happened: %s for request %s" % \ |
| (response.error, response.request)) |
| elif response.status != httplib.OK: |
| raise UserNotFoundError("request: %s status: %s body: %s" % \ |
| (response.request, response.status, response.body)) |
| |
| data = json.loads(response.body) # convert json string to dict |
| return data |
| |
| def adelete_user(self, uid): |
| """Asynchronously delete user. |
| |
| :param uid: user id. type str or int. |
| |
| :returns: |
| AsyncRequest object. You should call the aresp() method using this AsyncRequest |
| object as argument to get the final result or status of this asynchronous request. |
| """ |
| if type(uid) is int: |
| enc_uid = uid |
| else: |
| enc_uid = urllib.quote(uid,"") # replace special char with %xx |
| path = "%s/users/%s.json" % (self.apiversion, enc_uid) |
| request = AsyncRequest("DELETE", path, appkey=self.appkey) |
| request.set_rfunc(self._adelete_user_resp) |
| self._connection.make_request(request) |
| |
| return request |
| |
| def _adelete_user_resp(self, response): |
| """Private function to handle the AsyncResponse of the adelete_user request. |
| |
| :param response: AsyncResponse object. |
| |
| :returns: |
| None. |
| |
| :raises: |
| UserNotDeletedError. |
| |
| """ |
| if response.error is not None: |
| raise UserNotDeletedError("Exception happened: %s for request %s" % \ |
| (response.error, response.request)) |
| elif response.status != httplib.OK: |
| raise UserNotDeletedError("request: %s status: %s body: %s" % \ |
| (response.request, response.status, response.body)) |
| return None |
| |
| def acreate_item(self, iid, itypes, **params): |
| """Asynchronously create item. |
| |
| :param iid: item id. type str or int. |
| :param itypes: item types. Tuple of Str. |
| For example, if this item belongs to item types "t1", "t2", "t3", "t4", |
| then itypes=("t1", "t2", "t3", "t4"). |
| NOTE: if this item belongs to only one itype, use tuple of one element, eg. itypes=("t1",) |
| :param params: keyword arguments for optional attributes. |
| For example, latlng="123.4, 56.7". |
| :returns: |
| AsyncRequest object. You should call the aresp() method using this AsyncRequest |
| object as argument to get the final result or status of this asynchronous request. |
| """ |
| itypes_str = ",".join(map(str, itypes)) # convert to string and join items with "," |
| path = "%s/items.json" % self.apiversion |
| request = AsyncRequest("POST", path, appkey=self.appkey, iid=iid, itypes=itypes_str, **params) |
| request.set_rfunc(self._acreate_item_resp) |
| self._connection.make_request(request) |
| return request |
| |
| def _acreate_item_resp(self, response): |
| """Private function to handle the AsyncResponse of the acreate_item request |
| |
| :param response: AsyncResponse object. |
| |
| :returns: |
| None |
| :raises: |
| ItemNotCreatedError |
| |
| """ |
| if response.error is not None: |
| raise ItemNotCreatedError("Exception happened: %s for request %s" % \ |
| (response.error, response.request)) |
| elif response.status != httplib.CREATED: |
| raise ItemNotCreatedError("request: %s status: %s body: %s" % \ |
| (response.request, response.status, response.body)) |
| return None |
| |
| def aget_item(self, iid): |
| """Asynchronously get item |
| |
| :param iid: item id. type str or int. |
| |
| :returns: |
| AsyncRequest object. You should call the aresp() method using this AsyncRequest |
| object as argument to get the final result or status of this asynchronous request. |
| """ |
| if type(iid) is int: |
| enc_iid = iid |
| else: |
| enc_iid = urllib.quote(iid, "") |
| path = "%s/items/%s.json" % (self.apiversion, enc_iid) |
| request = AsyncRequest("GET", path, appkey=self.appkey) |
| request.set_rfunc(self._aget_item_resp) |
| self._connection.make_request(request) |
| return request |
| |
| def _aget_item_resp(self, response): |
| """Private function to handle the AsyncResponse of the aget_item request |
| |
| :param response: AsyncResponse object. |
| |
| :returns: |
| item data in dictionary format. |
| |
| :raises: |
| ItemNotFoundError. |
| |
| """ |
| if response.error is not None: |
| raise ItemNotFoundError("Exception happened: %s for request %s" % \ |
| (response.error, response.request)) |
| elif response.status != httplib.OK: |
| raise ItemNotFoundError("request: %s status: %s body: %s" % \ |
| (response.request, response.status, response.body)) |
| |
| data = json.loads(response.body) # convert json string to dict |
| return data |
| |
| def adelete_item(self, iid): |
| """Asynchronously delete item |
| |
| :param iid: item id. type str or int. |
| |
| :returns: |
| AsyncRequest object. You should call the aresp() method using this AsyncRequest |
| object as argument to get the final result or status of this asynchronous request. |
| """ |
| if type(iid) is int: |
| enc_iid = iid |
| else: |
| enc_iid = urllib.quote(iid, "") |
| path = "%s/items/%s.json" % (self.apiversion, enc_iid) |
| request = AsyncRequest("DELETE", path, appkey=self.appkey) |
| request.set_rfunc(self._adelete_item_resp) |
| self._connection.make_request(request) |
| return request |
| |
| def _adelete_item_resp(self, response): |
| """Private function to handle the AsyncResponse of the adelete_item request |
| |
| :param response: AsyncResponse object |
| |
| :returns: |
| None |
| |
| :raises: |
| ItemNotDeletedError |
| """ |
| if response.error is not None: |
| raise ItemNotDeletedError("Exception happened: %s for request %s" % \ |
| (response.error, response.request)) |
| elif response.status != httplib.OK: |
| raise ItemNotDeletedError("request: %s status: %s body: %s" % \ |
| (response.request, response.status, response.body)) |
| return None |
| |
| def aget_itemrec(self, uid, n, engine, **params): |
| """Asynchronously get recommendations |
| |
| :param uid: user id. type str or int. |
| :param n: number of recommendation. type int. |
| :param engine: name of the prediction engine. type str. |
| :param params: keyword arguments for optional attributes. |
| For example, latlng="123.4, 56.7" |
| :returns: |
| AsyncRequest object. You should call the aresp() method using this AsyncRequest |
| object as argument to get the final result or status of this asynchronous request. |
| """ |
| if type(uid) is int: |
| enc_uid = uid |
| else: |
| enc_uid = urllib.quote(uid,"") # replace special char with %xx |
| path = "%s/engines/itemrec/%s/topn.json" % (self.apiversion, engine) |
| request = AsyncRequest("GET", path, appkey=self.appkey, uid=enc_uid, n=n, **params) |
| request.set_rfunc(self._aget_itemrec_resp) |
| self._connection.make_request(request) |
| return request |
| |
| def _aget_itemrec_resp(self, response): |
| """Private function to handle the AsyncResponse of the aget_itemrec request |
| |
| :param response: AsyncResponse object |
| |
| :returns: |
| data in dictionary format. |
| |
| :raises: |
| ItemRecNotFoundError. |
| """ |
| if response.error is not None: |
| raise ItemRecNotFoundError("Exception happened: %s for request %s" % \ |
| (response.error, response.request)) |
| elif response.status != httplib.OK: |
| raise ItemRecNotFoundError("request: %s status: %s body: %s" % \ |
| (response.request, response.status, response.body)) |
| |
| data = json.loads(response.body) # convert json string to dict |
| return data |
| |
| def _auser_action_item(self, action, uid, iid, **params): |
| """Asynchronously create an user action on an item |
| |
| :param action: action type. type str. ("like", "dislike", "conversion", "rate", "view") |
| :param uid: user id. type str or int. |
| :param iid: item id. type str or int. |
| :param params: keyword arguments for optional attributes. |
| For example, latlng="123.4, 56.7" |
| For "rate" action, rate param is required. integer value of 1-5 (1 is least preferred and 5 is most preferred) (eg. rate=4) |
| :returns: |
| AsyncRequest object. You should call the aresp() method using this AsyncRequest |
| object as argument to get the final result or status of this asynchronous request. |
| """ |
| path = "%s/actions/u2i/%s.json" % (self.apiversion, action) |
| request = AsyncRequest("POST", path, appkey=self.appkey, uid=uid, iid=iid, **params) |
| request.set_rfunc(self._au2i_action_resp) |
| self._connection.make_request(request) |
| return request |
| |
| def _au2i_action_resp(self, response): |
| """Private function to handle the AsyncResponse of the auser_ACTION_item request |
| |
| :param response: AsyncResponse object |
| |
| :returns: |
| None |
| |
| :raises: |
| U2IActionNotCreatedError |
| """ |
| if response.error is not None: |
| raise U2IActionNotCreatedError("Exception happened: %s for request %s" % \ |
| (response.error, response.request)) |
| elif response.status != httplib.CREATED: |
| raise U2IActionNotCreatedError("request: %s status: %s body: %s" % \ |
| (response.request, response.status, response.body)) |
| return None |
| |
| def auser_conversion_item(self, uid, iid, **params): |
| """Asynchronously create an user conversion action on an item |
| |
| :param uid: user id. type str or int. |
| :param iid: item id. type str or int. |
| :param params: keyword arguments for optional attributes. |
| For example, latlng="123.4, 56.7" |
| :returns: |
| AsyncRequest object. You should call the aresp() method using this AsyncRequest |
| object as argument to get the final result or status of this asynchronous request. |
| """ |
| request = self._auser_action_item(action=CONVERSION_API, uid=uid, iid=iid, **params) |
| return request |
| |
| def auser_dislike_item(self, uid, iid, **params): |
| """Asynchronously create an user dislike action on an item |
| |
| :param uid: user id. type str or int. |
| :param iid: item id. type str or int. |
| :param params: keyword arguments for optional attributes. |
| For example, latlng="123.4, 56.7" |
| :returns: |
| AsyncRequest object. You should call the aresp() method using this AsyncRequest |
| object as argument to get the final result or status of this asynchronous request. |
| """ |
| request = self._auser_action_item(action=DISLIKE_API, uid=uid, iid=iid, **params) |
| return request |
| |
| def auser_like_item(self, uid, iid, **params): |
| """Asynchronously create an user like action on an item |
| |
| :param uid: user id. type str or int. |
| :param iid: item id. type str or int. |
| :param params: keyword arguments for optional attributes. |
| For example, latlng="123.4, 56.7" |
| :returns: |
| AsyncRequest object. You should call the aresp() method using this AsyncRequest |
| object as argument to get the final result or status of this asynchronous request. |
| """ |
| request = self._auser_action_item(action=LIKE_API, uid=uid, iid=iid, **params) |
| return request |
| |
| def auser_rate_item(self, uid, iid, rate, **params): |
| """Asynchronously create an user rate action on an item |
| |
| :param uid: user id. type str or int. |
| :param iid: item id. type str or int. |
| :param rate: rating. integer value of 1-5 (1 is least preferred and 5 is most preferred) |
| :param params: keyword arguments for optional attributes. |
| For example, latlng="123.4, 56.7" |
| :returns: |
| AsyncRequest object. You should call the aresp() method using this AsyncRequest |
| object as argument to get the final result or status of this asynchronous request. |
| """ |
| request = self._auser_action_item(action=RATE_API, uid=uid, iid=iid, rate=rate, **params) |
| return request |
| |
| def auser_view_item(self, uid, iid, **params): |
| """Asynchronously create an user view action on an item |
| |
| :param uid: user id. type str or int. |
| :param iid: item id. type str or int. |
| :param params: keyword arguments for optional attributes. |
| For example, latlng="123.4, 56.7" |
| :returns: |
| AsyncRequest object. You should call the aresp() method using this AsyncRequest |
| object as argument to get the final result or status of this asynchronous request. |
| """ |
| request = self._auser_action_item(action=VIEW_API, uid=uid, iid=iid, **params) |
| return request |
| |
| def aresp(self, request): |
| """Get the result of the asynchronous request |
| |
| :param request: AsyncRequest object. This object must be returned by the asynchronous request function |
| For example, to get the result of a aget_user() request, call this aresp() with the argument of |
| AsyncRequest object returned by aget_user(). |
| |
| :returns: |
| The result of this AsyncRequest. The return type is the same as the return type of corresponding blocking request. |
| |
| For example, |
| |
| Calling aresp() with acreate_user() AsyncRequest returns the same type as create_user(), which is None. |
| |
| Calling aresp() with aget_user() AsyncRequest returns the same type as get_user(), which is dictionary data. |
| |
| :raises: |
| Exception may be raised if there is error happened. The type of exception is the same as exception type |
| of the correspdoning blocking request. |
| |
| For example, |
| |
| Calling aresp() with acreate_user() AsyncRequest may raise UserNotCreatedError exception. |
| |
| Calling aresp() with aget_user() AsyncRequest may raise UserNotFoundError exception. |
| |
| """ |
| response = request.get_response() |
| result = request.rfunc(response) |
| return result |
| |
| |
| def create_user(self, uid, **params): |
| """Blocking request to create user |
| |
| :param uid: user id. type str or int. |
| :param params: keyword arguments for optional attributes. |
| For example, bday="1985-01-23", inactive="true". |
| |
| :returns: |
| None. |
| |
| :raises: |
| UserNotCreatedError. |
| |
| """ |
| request = self.acreate_user(uid, **params) |
| result = self.aresp(request) |
| return result |
| |
| def get_user(self, uid): |
| """Blocking request to get user |
| |
| :param uid: user id. type str or int. |
| |
| :returns: |
| User data in Dictionary format. |
| |
| :rasies: |
| UserNotFoundError. |
| |
| """ |
| request = self.aget_user(uid) |
| result = self.aresp(request) |
| return result |
| |
| def delete_user(self, uid): |
| """Blocking request to delete the user |
| |
| :param uid: user id. type str or int. |
| |
| :returns: |
| None. |
| |
| :raises: |
| UserNotDeletedError. |
| |
| """ |
| request = self.adelete_user(uid) |
| result = self.aresp(request) |
| return result |
| |
| def create_item(self, iid, itypes, **params): |
| """Blocking request to create item |
| |
| :param iid: item id. type str or int. |
| :param itypes: item types. Tuple of Str. |
| For example, if this item belongs to item types "t1", "t2", "t3", "t4", |
| then itypes=("t1", "t2", "t3", "t4"). |
| NOTE: if this item belongs to only one itype, use tuple of one element, eg. itypes=("t1",) |
| :param params: keyword arguments for optional attributes. |
| For example, latlng="123.4, 56.7". |
| |
| :returns: |
| None |
| |
| :raises: |
| ItemNotCreatedError |
| |
| """ |
| request = self.acreate_item(iid, itypes, **params) |
| result = self.aresp(request) |
| return result |
| |
| def get_item(self, iid): |
| """Blocking request to get item |
| |
| :param iid: item id. type str or int. |
| |
| :returns: |
| item data in dictionary format. |
| |
| :raises: |
| ItemNotFoundError. |
| |
| """ |
| request = self.aget_item(iid) |
| result = self.aresp(request) |
| return result |
| |
| def delete_item(self, iid): |
| """Blocking request to delete item |
| |
| :param iid: item id. type str or int. |
| |
| :returns: |
| None |
| |
| :raises: |
| ItemNotDeletedError |
| |
| """ |
| request = self.adelete_item(iid) |
| result = self.aresp(request) |
| return result |
| |
| def get_itemrec(self, uid, n, engine, **params): |
| """Blocking request to get recommendations |
| |
| :param uid: user id. type str or int. |
| :param n: number of recommendation. type int. |
| :param engine: name of the prediction engine. type str. |
| :param params: keyword arguments for optional attributes. |
| For example, latlng="123.4, 56.7" |
| |
| :returns: |
| data in dictionary format. |
| |
| :raises: |
| ItemRecNotFoundError. |
| |
| """ |
| request = self.aget_itemrec(uid, n, engine=engine, **params) |
| result = self.aresp(request) |
| return result |
| |
| def _user_action_item(self, action, uid, iid, **params): |
| """Blocking request to create user action on an item |
| |
| :param action: action type. type str. ("like", "dislike", "conversion", "rate", "view") |
| :param uid: user id. type str or int. |
| :param iid: item id. type str or int. |
| :param params: keyword arguments for optional attributes. |
| For example, latlng="123.4, 56.7" |
| For "rate" action, rate param is required. integer value of 1-5 (1 is least preferred and 5 is most preferred) (eg. rate=4) |
| :returns: |
| None |
| |
| :raises: |
| U2IActionNotCreatedError |
| """ |
| request = self._auser_action_item(action, uid, iid, **params) |
| result = self.aresp(request) |
| return result |
| |
| def user_conversion_item(self, uid, iid, **params): |
| """Blocking request to create user conversion action on an item |
| |
| :param uid: user id. type str or int. |
| :param iid: item id. type str or int. |
| :param params: keyword arguments for optional attributes. |
| For example, latlng="123.4, 56.7" |
| |
| :returns: |
| None |
| |
| :raises: |
| U2IActionNotCreatedError |
| """ |
| result = self._user_action_item(action=CONVERSION_API, uid=uid, iid=iid, **params) |
| return result |
| |
| def user_dislike_item(self, uid, iid, **params): |
| """Blocking request to create user dislike action on an item |
| |
| :param uid: user id. type str or int. |
| :param iid: item id. type str or int. |
| :param params: keyword arguments for optional attributes. |
| For example, latlng="123.4, 56.7" |
| |
| :returns: |
| None |
| |
| :raises: |
| U2IActionNotCreatedError |
| """ |
| result = self._user_action_item(action=DISLIKE_API, uid=uid, iid=iid, **params) |
| return result |
| |
| def user_like_item(self, uid, iid, **params): |
| """Blocking request to create user like action on an item |
| |
| :param uid: user id. type str or int. |
| :param iid: item id. type str or int. |
| :param params: keyword arguments for optional attributes. |
| For example, latlng="123.4, 56.7" |
| |
| :returns: |
| None |
| |
| :raises: |
| U2IActionNotCreatedError |
| """ |
| result = self._user_action_item(action=LIKE_API, uid=uid, iid=iid, **params) |
| return result |
| |
| def user_rate_item(self, uid, iid, rate, **params): |
| """Blocking request to create user rate action on an item |
| |
| :param uid: user id. type str or int. |
| :param iid: item id. type str or int. |
| :param rate: rating. integer value of 1-5 (1 is least preferred and 5 is most preferred) |
| :param params: keyword arguments for optional attributes. |
| For example, latlng="123.4, 56.7" |
| |
| :returns: |
| None |
| |
| :raises: |
| U2IActionNotCreatedError |
| """ |
| result = self._user_action_item(action=RATE_API, uid=uid, iid=iid, rate=rate, **params) |
| return result |
| |
| def user_view_item(self, uid, iid, **params): |
| """Blocking request to create user view action on an item |
| |
| :param uid: user id. type str or int. |
| :param iid: item id. type str or int. |
| :param params: keyword arguments for optional attributes. |
| For example, latlng="123.4, 56.7" |
| |
| :returns: |
| None |
| |
| :raises: |
| U2IActionNotCreatedError |
| """ |
| result = self._user_action_item(action=VIEW_API, uid=uid, iid=iid, **params) |
| return result |