<commit_before>'''
    webauth.service
    ---------------

    Provides OAuth 1.0/a, 2.0 and Ofly service containers.
'''

import requests
import json
import hashlib

from webauth.hook import OAuth1Hook

from urllib import quote, urlencode
from urlparse import parse_qsl, urlsplit
from datetime import datetime


def _parse_response(response):
    '''Attempts to coerce response.content into a dictionary.

    :param response: A Requests response object.
    '''
    if isinstance(response.content, str):
        try:
            content = json.loads(response.content)
        except ValueError:
            content = dict(parse_qsl(response.content))
        return content
    # TODO: rather than returning the content in the case of receiving
    # something we can't parse we should probably raise an error
    return response.content


class OflyService(object):
    '''An Ofly Service container.

    This class wraps an Ofly service. Most commonly, Shutterfly. The process
    is similar to that of OAuth 1.0 but simplified. Here we use Requests
    directly rather than relying on a hook.

    You might intialize :class:`OflyService` something like this::

        service = OflyService(name='example',
                              consumer_key='123',
                              consumer_secret='456',
                              authorize_url='http://example.com/authorize')

    A signed authorize URL is then produced via calling
    `service.get_authorize_url`. Once this has been visited by the client and
    assuming the client authorizes the request, subsequent API calls may be
    made through `service.request`.

    :param name: The service name.
    :param consumer_key: Client consumer key.
    :param consumer_secret: Client consumer secret.
    :param authorize_url: Authorize endpoint.
    '''
    TIMESTAMP_FORMAT = '%Y-%m-%dT%H:%M:%S.{0}Z'
    MICRO_TO_MILLISECONDS = 1000

    def __init__(self, name, consumer_key, consumer_secret, authorize_url):
        self.name = name

        self.consumer_key = consumer_key
        self.consumer_secret = consumer_secret

        self.authorize_url = authorize_url

    def _milliseconds(self, dt):
        return int(dt.microsecond / self.MICRO_TO_MILLISECONDS)

    def _sort_params(self, params):
        def sorting():
            for k in sorted(params.keys()):
                yield '='.join((k, params[k]))
        return '&'.join(sorting())

    def _sha1_sign_params(self, url, header_auth=False, **params):
        now = datetime.utcnow()
        time_format = self.TIMESTAMP_FORMAT.format(self._milliseconds(now))
        ofly_params = \
                {'oflyAppId': self.consumer_key,
                 'oflyHashMeth': 'SHA1',
                 'oflyTimestamp': now.strftime(time_format)}

        # select only the path for signing
        uri = urlsplit(url).path

        signature_base_string = self.consumer_secret \
                                + uri \
                                + '?' \
                                + self._sort_params(params) \
                                + '&' \
                                + self._sort_params(ofly_params)

        params['oflyApiSig'] = hashlib.sha1(signature_base_string).hexdigest()

        if not header_auth:
            # don't use header authentication
            params = dict(params.items() + ofly_params.items())
            return self._sort_params(params)
        else:
            # return the raw ofly_params for use in the header
            return self._sort_params(params), ofly_params

    def get_authorize_url(self, remote_user=None, redirect_uri=None, **params):<commit_msg>add link to shutterfly signature docs; improve a variable name<commit_after>'''
    webauth.service
    ---------------

    Provides OAuth 1.0/a, 2.0 and Ofly service containers.
'''

import requests
import json
import hashlib

from webauth.hook import OAuth1Hook

from urllib import quote, urlencode
from urlparse import parse_qsl, urlsplit
from datetime import datetime


def _parse_response(response):
    '''Attempts to coerce response.content into a dictionary.

    :param response: A Requests response object.
    '''
    if isinstance(response.content, str):
        try:
            content = json.loads(response.content)
        except ValueError:
            content = dict(parse_qsl(response.content))
        return content
    # TODO: rather than returning the content in the case of receiving
    # something we can't parse we should probably raise an error
    return response.content


class OflyService(object):
    '''An Ofly Service container.

    This class wraps an Ofly service. Most commonly, Shutterfly. The process
    is similar to that of OAuth 1.0 but simplified. Here we use Requests
    directly rather than relying on a hook.

    You might intialize :class:`OflyService` something like this::

        service = OflyService(name='example',
                              consumer_key='123',
                              consumer_secret='456',
                              authorize_url='http://example.com/authorize')

    A signed authorize URL is then produced via calling
    `service.get_authorize_url`. Once this has been visited by the client and
    assuming the client authorizes the request, subsequent API calls may be
    made through `service.request`.

    :param name: The service name.
    :param consumer_key: Client consumer key.
    :param consumer_secret: Client consumer secret.
    :param authorize_url: Authorize endpoint.
    '''
    TIMESTAMP_FORMAT = '%Y-%m-%dT%H:%M:%S.{0}Z'
    MICRO_TO_MILLISECONDS = 1000

    def __init__(self, name, consumer_key, consumer_secret, authorize_url):
        self.name = name

        self.consumer_key = consumer_key
        self.consumer_secret = consumer_secret

        self.authorize_url = authorize_url

    def _milliseconds(self, dt):
        return int(dt.microsecond / self.MICRO_TO_MILLISECONDS)

    def _sort_params(self, params):
        def sorting():
            for k in sorted(params.keys()):
                yield '='.join((k, params[k]))
        return '&'.join(sorting())

    def _sha1_sign_params(self, url, header_auth=False, **params):
        # signing method described here:
        # http://www.shutterfly.com/documentation/OflyCallSignature.sfly
        now = datetime.utcnow()
        time_format = self.TIMESTAMP_FORMAT.format(self._milliseconds(now))
        ofly_params = \
                {'oflyAppId': self.consumer_key,
                 'oflyHashMeth': 'SHA1',
                 'oflyTimestamp': now.strftime(time_format)}

        # select only the path for signing
        uri_path = urlsplit(url).path

        signature_base_string = self.consumer_secret \
                                + uri_path \
                                + '?' \
                                + self._sort_params(params) \
                                + '&' \
                                + self._sort_params(ofly_params)

        params['oflyApiSig'] = hashlib.sha1(signature_base_string).hexdigest()

        if not header_auth:
            # don't use header authentication
            params = dict(params.items() + ofly_params.items())
            return self._sort_params(params)
        else:
            # return the raw ofly_params for use in the header
            return self._sort_params(params), ofly_params

    def get_authorize_url(self, remote_user=None, redirect_uri=None, **params):
{'fraction_non_alphanumeric': 0.0880503144654088, 'fraction_numerical': 0.005620232838217583, 'mean_word_length': 2.2609075043630016, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 1, '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': '7276637', 'n_tokens_mistral': 2105, 'n_tokens_neox': 1993, 'n_words': 581}