<commit_before># coding=utf-8
"""
The end developer will do most of their work with the PayPalInterface class found
in this module. Configuration, querying, and manipulation can all be done
with it.
"""

import types
import logging
from pprint import pformat

import requests

from paypal.settings import PayPalConfig
from paypal.response import PayPalResponse
from paypal.exceptions import PayPalError, PayPalAPIResponseError
from paypal.compat import is_py3

if is_py3:
    #noinspection PyUnresolvedReferences
    import urllib.parse
else:
    import urllib

logger = logging.getLogger('paypal.interface')

class PayPalInterface(object):
    """
    The end developers will do 95% of their work through this class. API
    queries, configuration, etc, all go through here. See the __init__ method
    for config related details.
    """
    def __init__(self, config=None, **kwargs):
        """
        Constructor, which passes all config directives to the config class
        via kwargs. For example:

            paypal = PayPalInterface(API_USERNAME='somevalue')

        Optionally, you may pass a 'config' kwarg to provide your own
        PayPalConfig object.
        """
        if config:
            # User provided their own PayPalConfig object.
            self.config = config
        else:
            # Take the kwargs and stuff them in a new PayPalConfig object.
            self.config = PayPalConfig(**kwargs)

    def _encode_utf8(self, **kwargs):
        """
        UTF8 encodes all of the NVP values.
        """
        if is_py3:
            # This is only valid for Python 2. In Python 3, unicode is
            # everywhere (yay).
            return kwargs

        unencoded_pairs = kwargs
        for i in unencoded_pairs.keys():
            #noinspection PyUnresolvedReferences
            if isinstance(unencoded_pairs[i], types.UnicodeType):
                unencoded_pairs[i] = unencoded_pairs[i].encode('utf-8')
        return unencoded_pairs

    def _check_required(self, requires, **kwargs):
        """
        Checks kwargs for the values specified in 'requires', which is a tuple
        of strings. These strings are the NVP names of the required values.
        """
        for req in requires:
            # PayPal api is never mixed-case.
            if req.lower() not in kwargs and req.upper() not in kwargs:
                raise PayPalError('missing required : %s' % req)

    def _sanitize_locals(self, data):
        """
        Remove the 'self' key in locals()
        It's more explicit to do it in one function
        """
        if 'self' in data:
            data = data.copy()
            del data['self']

        return data

    def _call(self, method, **kwargs):
        """
        Wrapper method for executing all API commands over HTTP. This method is
        further used to implement wrapper methods listed here:

        https://www.x.com/docs/DOC-1374

        ``method`` must be a supported NVP method listed at the above address.

        ``kwargs`` will be a hash of
        """
        # This dict holds the key/value pairs to pass to the PayPal API.
        url_values = {
            'METHOD': method,
            'VERSION': self.config.API_VERSION,
        }

        if self.config.API_AUTHENTICATION_MODE == "3TOKEN":
            url_values['USER'] = self.config.API_USERNAME
            url_values['PWD'] = <PASSWORD>
            url_values['SIGNATURE'] = self.config.API_SIGNATURE
        elif self.config.API_AUTHENTICATION_MODE == "UNIPAY":
            url_values['SUBJECT'] = self.config.UNIPAY_SUBJECT

        # All values passed to PayPal API must be uppercase.
        for key, value in kwargs.items():
            url_values[key.upper()] = value

        # This shows all of the key/val pairs we're sending to PayPal.
        if logger.isEnabledFor(logging.DEBUG):
            logger.debug('PayPal NVP Query Key/Vals:\n%s' % pformat(url_values))

        req = requests.get(
            self.config.API_ENDPOINT,
            params=url_values,
            timeout=self.config.HTTP_TIMEOUT,
            verify=self.config.API_CA_CERTS,
        )

        # Call paypal API
        response = PayPalResponse(req.text, self.config)

        logger.debug('PayPal NVP API Endpoint: %s' % self.config.API_ENDPOINT)

        if not response.success:
            logger.error('A PayPal API error was encountered.')
            logger.error('PayPal NVP Query Key/Vals:\n%s' % pformat(url_values))
            logger.error('PayPal NVP Query Response')
            logger.error(response)
            raise PayPalAPIResponseError(response)

        return response

    def address_verify(self, email, street, zip):
        """Shortcut for the AddressVerify method.<commit_msg>use post method for call to paypal<commit_after># coding=utf-8
"""
The end developer will do most of their work with the PayPalInterface class found
in this module. Configuration, querying, and manipulation can all be done
with it.
"""

import types
import logging
from pprint import pformat

import requests

from paypal.settings import PayPalConfig
from paypal.response import PayPalResponse
from paypal.exceptions import PayPalError, PayPalAPIResponseError
from paypal.compat import is_py3

if is_py3:
    #noinspection PyUnresolvedReferences
    import urllib.parse
else:
    import urllib

logger = logging.getLogger('paypal.interface')

class PayPalInterface(object):
    """
    The end developers will do 95% of their work through this class. API
    queries, configuration, etc, all go through here. See the __init__ method
    for config related details.
    """
    def __init__(self, config=None, **kwargs):
        """
        Constructor, which passes all config directives to the config class
        via kwargs. For example:

            paypal = PayPalInterface(API_USERNAME='somevalue')

        Optionally, you may pass a 'config' kwarg to provide your own
        PayPalConfig object.
        """
        if config:
            # User provided their own PayPalConfig object.
            self.config = config
        else:
            # Take the kwargs and stuff them in a new PayPalConfig object.
            self.config = PayPalConfig(**kwargs)

    def _encode_utf8(self, **kwargs):
        """
        UTF8 encodes all of the NVP values.
        """
        if is_py3:
            # This is only valid for Python 2. In Python 3, unicode is
            # everywhere (yay).
            return kwargs

        unencoded_pairs = kwargs
        for i in unencoded_pairs.keys():
            #noinspection PyUnresolvedReferences
            if isinstance(unencoded_pairs[i], types.UnicodeType):
                unencoded_pairs[i] = unencoded_pairs[i].encode('utf-8')
        return unencoded_pairs

    def _check_required(self, requires, **kwargs):
        """
        Checks kwargs for the values specified in 'requires', which is a tuple
        of strings. These strings are the NVP names of the required values.
        """
        for req in requires:
            # PayPal api is never mixed-case.
            if req.lower() not in kwargs and req.upper() not in kwargs:
                raise PayPalError('missing required : %s' % req)

    def _sanitize_locals(self, data):
        """
        Remove the 'self' key in locals()
        It's more explicit to do it in one function
        """
        if 'self' in data:
            data = data.copy()
            del data['self']

        return data

    def _call(self, method, **kwargs):
        """
        Wrapper method for executing all API commands over HTTP. This method is
        further used to implement wrapper methods listed here:

        https://www.x.com/docs/DOC-1374

        ``method`` must be a supported NVP method listed at the above address.

        ``kwargs`` will be a hash of
        """
        # This dict holds the key/value pairs to pass to the PayPal API.
        url_values = {
            'METHOD': method,
            'VERSION': self.config.API_VERSION,
        }

        if self.config.API_AUTHENTICATION_MODE == "3TOKEN":
            url_values['USER'] = self.config.API_USERNAME
            url_values['PWD'] = self.config.API_PASSWORD
            url_values['SIGNATURE'] = self.config.API_SIGNATURE
        elif self.config.API_AUTHENTICATION_MODE == "UNIPAY":
            url_values['SUBJECT'] = self.config.UNIPAY_SUBJECT

        # All values passed to PayPal API must be uppercase.
        for key, value in kwargs.items():
            url_values[key.upper()] = value

        # This shows all of the key/val pairs we're sending to PayPal.
        if logger.isEnabledFor(logging.DEBUG):
            logger.debug('PayPal NVP Query Key/Vals:\n%s' % pformat(url_values))

        req = requests.post(
            self.config.API_ENDPOINT,
            data=url_values,
            timeout=self.config.HTTP_TIMEOUT,
            verify=self.config.API_CA_CERTS,
            )

        # Call paypal API
        response = PayPalResponse(req.text, self.config)

        logger.debug('PayPal NVP API Endpoint: %s' % self.config.API_ENDPOINT)

        if not response.success:
            logger.error('A PayPal API error was encountered.')
            logger.error('PayPal NVP Query Key/Vals:\n%s' % pformat(url_values))
            logger.error('PayPal NVP Query Response')
            logger.error(response)
            raise PayPalAPIResponseError(response)

        return response

    def address_verify(self, email, street, zip):
        """Shortcut for the AddressVerify method.
{'fraction_non_alphanumeric': 0.08249581239530988, 'fraction_numerical': 0.0033500837520938024, 'mean_word_length': 2.265982905982906, 'pattern_counts': {'":': 4, '<': 4, '<?xml version=': 0, '>': 4, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4696856', 'n_tokens_mistral': 2631, 'n_tokens_neox': 2542, 'n_words': 877}