<commit_before>import requests

from constants import PRODUCT_SEARCH_PARAMS, PRODUCT_DESCRIPTION_TYPES, \
    BASE_URL


class BestBuyProductAPIError(Exception):

    """
        Errors generated before BestBuy servers respond to a call
    """
    pass


class BestBuyProductsAPI(object):

    def __init__(self, api_key):
        """
            :param api_key: best buy developer API key.
        """
        self.api_key = api_key.strip()

    def _call(self, payload):
        """
            Actual call ot the Best Buy API.

            :rType: JSON
        """
        valid_payload = self._validate_params(payload)
        url, valid_payload = self._build_url(valid_payload)
        request = requests.get(url, params=valid_payload)

        if request.headers['content-type'] == "text/json":
            return request.json()

        return request.content

    def _build_url(self, payload):
        """
            Receives a payload (dict) with all the necessary make a call to
            the Best Buy API and returns a string URL that includes the query
            and the dict parameters pre-processed for a API call to be made.

            :param paylod: dictionary with request parameters

            :rType: tuple that contains the url that includes the query and
                    the parameters pre-processed for a API call to be made.
        """

        query = payload['query']

        # Pre-process paramenters before submitting payload.

        out = dict()

        for key, value in payload['params'].iteritems():
            if type(value) is list:
                out[key] = ",".join(value)
            else:
                out[key] = value

        # Add key to params
        out['apiKey'] = self.api_key

        url = BASE_URL + "products({0})".format(query)

        return (url, out)

    def _validate_params(self, payload):
        """
            Validate parameters, double check that there are no None values
            in the keys.

            :param payload: dictionary, with the parameters to be used to make
                            a request.
        """

        for key, value in payload['params'].iteritems():

            if key not in PRODUCT_SEARCH_PARAMS:
                err_msg = ("{0} is an invalid Product"
                           " Search Parameter".format(key))
                raise BestBuyProductAPIError(err_msg)

            if value is None:
                err_msg = "Key {0} can't have None for a value".format(key)
                raise BestBuyProductAPIError(err_msg)

        return payload

    # =================================
    #   Search by description or SKU
    # =================================

    def search_by_description(self, description_type, description, **kwargs):
        """
            Searches the product API using description parameter

            :param description_type: Integer from 1 to 4 to determine the type
                                     of description the call is going to use.
                                     The integers represent:
                                     - 1: name<commit_msg>minor param validation update<commit_after>import requests

from constants import PRODUCT_SEARCH_PARAMS, PRODUCT_DESCRIPTION_TYPES, \
    API_SEARCH_PARAMS, BASE_URL


class BestBuyProductAPIError(Exception):

    """
        Errors generated before BestBuy servers respond to a call
    """
    pass


class BestBuyProductsAPI(object):

    def __init__(self, api_key):
        """
            :param api_key: best buy developer API key.
        """
        self.api_key = api_key.strip()

    def _call(self, payload):
        """
            Actual call ot the Best Buy API.

            :rType: JSON
        """
        valid_payload = self._validate_params(payload)
        url, valid_payload = self._build_url(valid_payload)
        request = requests.get(url, params=valid_payload)

        if request.headers['content-type'] == "text/json":
            return request.json()

        return request.content

    def _build_url(self, payload):
        """
            Receives a payload (dict) with all the necessary make a call to
            the Best Buy API and returns a string URL that includes the query
            and the dict parameters pre-processed for a API call to be made.

            :param paylod: dictionary with request parameters

            :rType: tuple that contains the url that includes the query and
                    the parameters pre-processed for a API call to be made.
        """

        query = payload['query']

        # Pre-process paramenters before submitting payload.

        out = dict()

        for key, value in payload['params'].iteritems():
            if type(value) is list:
                out[key] = ",".join(value)
            else:
                out[key] = value

        # Add key to params
        out['apiKey'] = self.api_key

        url = BASE_URL + "products({0})".format(query)

        return (url, out)

    def _validate_params(self, payload):
        """
            Validate parameters, double check that there are no None values
            in the keys.

            :param payload: dictionary, with the parameters to be used to make
                            a request.
        """

        for key, value in payload['params'].iteritems():

            if (key not in PRODUCT_SEARCH_PARAMS
                    or key not in API_SEARCH_PARAMS):
                err_msg = ("{0} is an invalid Product"
                           " Search Parameter".format(key))
                raise BestBuyProductAPIError(err_msg)

            if value is None:
                err_msg = "Key {0} can't have None for a value".format(key)
                raise BestBuyProductAPIError(err_msg)

        return payload

    # =================================
    #   Search by description or SKU
    # =================================

    def search_by_description(self, description_type, description, **kwargs):
        """
            Searches the product API using description parameter

            :param description_type: Integer from 1 to 4 to determine the type
                                     of description the call is going to use.
                                     The integers represent:
                                     - 1: name
{'fraction_non_alphanumeric': 0.09342996691350244, 'fraction_numerical': 0.0018906570033086498, 'mean_word_length': 1.7964757709251102, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6134055', 'n_tokens_mistral': 1626, 'n_tokens_neox': 1516, 'n_words': 548}