<commit_before># Copyright (c) 2012 Andy Davidoff http://www.disruptek.com/
# Copyright (c) 2010 Jason R. Coombs http://www.jaraco.com/
# Copyright (c) 2008 Chris Moyer http://coredumped.org/
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish, dis-
# tribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the fol-
# lowing conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

import urllib
import uuid
from boto.connection import AWSQueryConnection
from boto.fps.exception import ResponseErrorFactory
from boto.fps.response import ResponseFactory
import boto.fps.response

__all__ = ['FPSConnection']

decorated_attrs = ('action', 'response')

def add_attrs_from(func, to):
    for attr in decorated_attrs:
        setattr(to, attr, getattr(func, attr, None))
    return to

def complex_amounts(*fields):
    def decorator(func):
        def wrapper(self, *args, **kw):
            for field in filter(kw.has_key, fields):
                amount = kw.pop(field)
                kw[field + '.Value'] = getattr(amount, 'Value', str(amount))
                kw[field + '.CurrencyCode'] = getattr(amount, 'CurrencyCode',
                                                      self.currencycode)
            return func(self, *args, **kw)
        wrapper.__doc__ = "{0}\nComplex Amounts: {1}".format(func.__doc__,
                                                 ', '.join(fields))
        return add_attrs_from(func, to=wrapper)
    return decorator

def requires(*groups):

    def decorator(func):

        def wrapper(*args, **kw):
            hasgroup = lambda x: len(x) == len(filter(kw.has_key, x))
            if 1 != len(filter(hasgroup, groups)):
                message = ' OR '.join(['+'.join(g) for g in groups])
                message = "{0} requires {1} argument(s)" \
                          "".format(func.action, message)
                raise KeyError(message)
            return func(*args, **kw)
        message = ' OR '.join(['+'.join(g) for g in groups])
        wrapper.__doc__ = "{0}\nRequired: {1}".format(func.__doc__,
                                                           message)
        return add_attrs_from(func, to=wrapper)
    return decorator

def needs_caller_reference(func):

    def wrapper(*args, **kw):
        kw.setdefault('CallerReference', uuid.uuid4())
        return func(*args, **kw)
    wrapper.__doc__ = "{0}\nUses CallerReference, defaults " \
                      "to uuid.uuid4()".format(func.__doc__)
    return add_attrs_from(func, to=wrapper)

def needs_caller_key(func):

    def wrapper(self, *args, **kw):
        kw.setdefault('callerKey', self.aws_access_key_id)
        return func(self, *args, **kw)
    wrapper.__doc__ = "{0}\nUses callerKey, defaults to your " \
                      "AWS Access Key ID".format(func.__doc__)
    return add_attrs_from(func, to=wrapper)

def api_action(*api):

    def decorator(func):
        action = ''.join(api or map(str.capitalize, func.func_name.split('_')))
        response = ResponseFactory(action)
        if hasattr(boto.fps.response, action + 'Response'):
            response = getattr(boto.fps.response, action + 'Response')

        def wrapper(self, *args, **kw):
            return func(self, action, response, *args, **kw)
        wrapper.action, wrapper.response = action, response
        wrapper.__doc__ = "FPS {0} API call\n{1}".format(action,
                                                         func.__doc__)
        return wrapper
    return decorator

class FPSConnection(AWSQueryConnection):

    APIVersion = '2010-08-28'
    ResponseError = ResponseErrorFactory
    currencycode = 'USD'

    def __init__(self, *args, **kw):
        self.currencycode = kw.pop('CurrencyCode', self.currencycode)
        kw.setdefault('host', 'fps.sandbox.amazonaws.com')
        AWSQueryConnection.__init__(self, *args, **kw)

    def _required_auth_capability(self):
        return ['fps']

    @needs_caller_reference
    @complex_amounts('SettlementAmount')
    @requires(['CreditInstrumentId', 'SettlementAmount.Value',
               'SenderTokenId',      'SettlementAmount.CurrencyCode'])
    @api_action()
    def settle_debt(self, action, response, **kw):
        """Allows a caller to initiate a transaction that atomically
           transfers money from a sender's payment instrument to the
           recipient, while decreasing corresponding debt balance.
        """
        return self.get_object(action, kw, response)

    @requires(['TransactionId'])
    @api_action()
    def get_transaction_status(self, action, response, **kw):
        """Gets the latest status of a transaction.
        """
        return self.get_object(action, kw, response)

    @requires(['StartDate'])
    @api_action()
    def get_account_activity(self, action, response, **kw):
        """Returns transactions for a given date range.
        """
        return self.get_object(action, kw, response)

    @requires(['TransactionId'])
    @api_action()
    def get_transaction(self, action, response, **kw):
        """Returns all details of a transaction.
        """
        return self.get_object(action, kw, response)

    @api_action()
    def get_outstanding_debt_balance(self, action, response):
        """Returns the total outstanding balance for all the credit
           instruments for the given creditor account.
        """
        return self.get_object(action, {}, response)

    @requires(['PrepaidInstrumentId'])
    @api_action()
    def get_prepaid_balance(self, action, response, **kw):
        """Returns the balance available on the given prepaid instrument.
        """
        return self.get_object(action, kw, response)

    @api_action()
    def get_total_prepaid_liability(self, action, response):
        """Returns the total liability held by the given account
           corresponding to all the prepaid instruments owned by the
           account.
        """
        return self.get_object(action, {}, response)

    @api_action()
    def get_account_balance(self, action, response):
        """Returns the account balance for an account in real time.
        """
        return self.get_object(action, {}, response)

    @needs_caller_reference
    @requires(['PaymentInstruction', 'TokenType'])
    @api_action()
    def install_payment_instruction(self, action, response, **kw):
        """Installs a payment instruction for caller.
        """
        return self.get_object(action, kw, response)

    @needs_caller_key
    @needs_caller_reference
    @requires(['returnURL', 'pipelineName'])
    def cbui_url(self, **kw):
        """Generate a signed URL for the Co-Branded service API given
           arguments as payload.
        """
        sandbox = 'sandbox' in self.host and 'payments-sandbox' or 'payments'
        endpoint = 'authorize.{0}.amazon.com'.format(sandbox)
        base = '/cobranded-ui/actions/start'

        validpipelines = ('SingleUse', 'MultiUse', 'Recurring', 'Recipient',
                          'SetupPrepaid', 'SetupPostpaid', 'EditToken')
        assert kw['pipelineName'] in validpipelines, "Invalid pipelineName"
        kw.update({
            'signatureMethod':  'HmacSHA256',
            'signatureVersion': '2',
        })

        safestr = lambda x: x is not None and str(x) or ''
        safequote = lambda x: urllib.quote(safestr(x), safe='~')
        payload = sorted([(k, safequote(v)) for k, v in kw.items()])

        encoded = lambda p: '&'.join([k + '=' + v for k, v in p])
        canonical = '\n'.join(['GET', endpoint, base, encoded(payload)])
        signature = self._auth_handler.sign_string(canonical)
        payload += [('signature', safequote(signature))]
        payload.sort()

        return 'https://{0}{1}?{2}'.format(endpoint, base, encoded(payload))

    @needs_caller_reference
    @complex_amounts('TransactionAmount')
    @requires(['SenderTokenId', 'TransactionAmount.Value',
                                'TransactionAmount.CurrencyCode'])
    @api_action()
    def reserve(self, action, response, **kw):
        """Reserve API is part of the Reserve and Settle API conjunction
           that serve the purpose of a pay where the authorization and
           settlement have a timing difference.
        """
        return self.get_object(action, kw, response)

    @needs_caller_reference
    @complex_amounts('TransactionAmount')
    @requires(['SenderTokenId', 'TransactionAmount.Value',
                                'TransactionAmount.CurrencyCode'])
    @api_action()
    def pay(self, action, response, **kw):
        """Allows calling applications to move money from a sender to
           a recipient.
        """
        return self.get_object(action, kw, response)

    @requires(['TransactionId'])
    @api_action()
    def cancel(self, action, response, **kw):
        """Cancels an ongoing transaction and puts it in cancelled state.
        """
        return self.get_object(action, kw, response)

    @complex_amounts('TransactionAmount')
    @requires(['ReserveTransactionId', 'TransactionAmount.Value',
                                       'TransactionAmount.CurrencyCode'])
    @api_action()
    def settle(self, action, response, **kw):
        """The Settle API is used in conjunction with the Reserve API and
           is used to settle previously reserved transaction.
        """
        return self.get_object(action, kw, response)

    @complex_amounts('RefundAmount')
    @requires(['TransactionId',   'RefundAmount.Value',
               'CallerReference', 'RefundAmount.CurrencyCode'])
    @api_action()
    def refund(self, action, response, **kw):
        """Refunds a previously completed transaction.
        """
        return self.get_object(action, kw, response)

    @requires(['RecipientTokenId'])
    @api_action()
    def get_recipient_verification_status(self, action, response, **kw):
        """Returns the recipient status.
        """
        return self.get_object(action, kw, response)

    @requires(['CallerReference'], ['TokenId'])
    @api_action()
    def get_token_by_caller(self, action, response, **kw):
        """Returns the details of a particular token installed by this
           calling application using the subway co-branded UI.
        """
        return self.get_object(action, kw, response)

    @requires(['UrlEndPoint', 'HttpParameters'])
    @api_action()
    def verify_signature(self, action, response, **kw):
        """Verify the signature that FPS sent in IPN or callback urls.
        """
        return self.get_object(action, kw, response)

    @api_action()
    def get_tokens(self, action, response, **kw):
        """Returns a list of tokens installed on the given account.
        """
        return self.get_object(action, kw, response)

    @requires(['TokenId'])
    @api_action()
    def get_token_usage(self, action, response, **kw):
        """Returns the usage of a token.
        """
        return self.get_object(action, kw, response)

    @requires(['TokenId'])
    @api_action()
    def cancel_token(self, action, response, **kw):
        """Cancels any token installed by the calling application on
           its own account.
        """
        return self.get_object(action, kw, response)

    @needs_caller_reference
    @complex_amounts('FundingAmount')
    @requires(['PrepaidInstrumentId', 'FundingAmount.Value',
               'SenderTokenId',       'FundingAmount.CurrencyCode'])
    @api_action()
    def fund_prepaid(self, action, response, **kw):
        """Funds the prepaid balance on the given prepaid instrument.
        """
        return self.get_object(action, kw, response)

    @requires(['CreditInstrumentId'])
    @api_action()
    def get_debt_balance(self, action, response, **kw):
        """Returns the balance corresponding to the given credit instrument.
        """
        return self.get_object(action, kw, response)

    @needs_caller_reference
    @complex_amounts('AdjustmentAmount')
    @requires(['CreditInstrumentId', 'AdjustmentAmount.Value',
                                     'AdjustmentAmount.CurrencyCode'])
    @api_action()
    def write_off_debt(self, action, response, **kw):
        """Allows a creditor to write off the debt balance accumulated
           partially or fully at any time.
        """
        return self.get_object(action, kw, response)

    @requires(['SubscriptionId'])
    @api_action()
    def get_transactions_for_subscription(self, action, response, **kw):
        """Returns the transactions for a given subscriptionID.
        """
        return self.get_object(action, kw, response)

    @requires(['SubscriptionId'])
    @api_action()
    def get_subscription_details(self, action, response, **kw):
        """Returns the details of Subscription for a given subscriptionID.
        """
        return self.get_object(action, kw, response)

    @needs_caller_reference
    @complex_amounts('RefundAmount')
    @requires(['SubscriptionId'])
    @api_action()
    def cancel_subscription_and_refund(self, action, response, **kw):
        """Cancels a subscription.
        """
        message = "If you specify a RefundAmount, " \
                  "you must specify CallerReference."
        assert not 'RefundAmount.Value' in kw \
                or 'CallerReference' in kw, message
        return self.get_object(action, kw, response)

    @requires(['TokenId'])
    @api_action()
    def get_payment_instruction(self, action, response, **kw):
        """Gets the payment instruction of a token.
        """
        return self.get_object(action, kw, response)
<commit_msg>tweak decorators to handle non-API methods remove @needs_caller_key; fold into cbui_url()<commit_after># Copyright (c) 2012 Andy Davidoff http://www.disruptek.com/
# Copyright (c) 2010 Jason R. Coombs http://www.jaraco.com/
# Copyright (c) 2008 Chris Moyer http://coredumped.org/
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish, dis-
# tribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the fol-
# lowing conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

import urllib
import uuid
from boto.connection import AWSQueryConnection
from boto.fps.exception import ResponseErrorFactory
from boto.fps.response import ResponseFactory
import boto.fps.response

__all__ = ['FPSConnection']

decorated_attrs = ('action', 'response')

def add_attrs_from(func, to):
    for attr in decorated_attrs:
        setattr(to, attr, getattr(func, attr, None))
    return to

def complex_amounts(*fields):
    def decorator(func):
        def wrapper(self, *args, **kw):
            for field in filter(kw.has_key, fields):
                amount = kw.pop(field)
                kw[field + '.Value'] = getattr(amount, 'Value', str(amount))
                kw[field + '.CurrencyCode'] = getattr(amount, 'CurrencyCode',
                                                      self.currencycode)
            return func(self, *args, **kw)
        wrapper.__doc__ = "{0}\nComplex Amounts: {1}".format(func.__doc__,
                                                 ', '.join(fields))
        return add_attrs_from(func, to=wrapper)
    return decorator

def requires(*groups):

    def decorator(func):

        def wrapper(*args, **kw):
            hasgroup = lambda x: len(x) == len(filter(kw.has_key, x))
            if 1 != len(filter(hasgroup, groups)):
                message = ' OR '.join(['+'.join(g) for g in groups])
                message = "{0} requires {1} argument(s)" \
                          "".format(getattr(func, 'action', 'Method'), message)
                raise KeyError(message)
            return func(*args, **kw)
        message = ' OR '.join(['+'.join(g) for g in groups])
        wrapper.__doc__ = "{0}\nRequired: {1}".format(func.__doc__,
                                                           message)
        return add_attrs_from(func, to=wrapper)
    return decorator

def needs_caller_reference(func):

    def wrapper(*args, **kw):
        kw.setdefault('CallerReference', uuid.uuid4())
        return func(*args, **kw)
    wrapper.__doc__ = "{0}\nUses CallerReference, defaults " \
                      "to uuid.uuid4()".format(func.__doc__)
    return add_attrs_from(func, to=wrapper)

def api_action(*api):

    def decorator(func):
        action = ''.join(api or map(str.capitalize, func.func_name.split('_')))
        response = ResponseFactory(action)
        if hasattr(boto.fps.response, action + 'Response'):
            response = getattr(boto.fps.response, action + 'Response')

        def wrapper(self, *args, **kw):
            return func(self, action, response, *args, **kw)
        wrapper.action, wrapper.response = action, response
        wrapper.__doc__ = "FPS {0} API call\n{1}".format(action,
                                                         func.__doc__)
        return wrapper
    return decorator

class FPSConnection(AWSQueryConnection):

    APIVersion = '2010-08-28'
    ResponseError = ResponseErrorFactory
    currencycode = 'USD'

    def __init__(self, *args, **kw):
        self.currencycode = kw.pop('CurrencyCode', self.currencycode)
        kw.setdefault('host', 'fps.sandbox.amazonaws.com')
        AWSQueryConnection.__init__(self, *args, **kw)

    def _required_auth_capability(self):
        return ['fps']

    @needs_caller_reference
    @complex_amounts('SettlementAmount')
    @requires(['CreditInstrumentId', 'SettlementAmount.Value',
               'SenderTokenId',      'SettlementAmount.CurrencyCode'])
    @api_action()
    def settle_debt(self, action, response, **kw):
        """Allows a caller to initiate a transaction that atomically
           transfers money from a sender's payment instrument to the
           recipient, while decreasing corresponding debt balance.
        """
        return self.get_object(action, kw, response)

    @requires(['TransactionId'])
    @api_action()
    def get_transaction_status(self, action, response, **kw):
        """Gets the latest status of a transaction.
        """
        return self.get_object(action, kw, response)

    @requires(['StartDate'])
    @api_action()
    def get_account_activity(self, action, response, **kw):
        """Returns transactions for a given date range.
        """
        return self.get_object(action, kw, response)

    @requires(['TransactionId'])
    @api_action()
    def get_transaction(self, action, response, **kw):
        """Returns all details of a transaction.
        """
        return self.get_object(action, kw, response)

    @api_action()
    def get_outstanding_debt_balance(self, action, response):
        """Returns the total outstanding balance for all the credit
           instruments for the given creditor account.
        """
        return self.get_object(action, {}, response)

    @requires(['PrepaidInstrumentId'])
    @api_action()
    def get_prepaid_balance(self, action, response, **kw):
        """Returns the balance available on the given prepaid instrument.
        """
        return self.get_object(action, kw, response)

    @api_action()
    def get_total_prepaid_liability(self, action, response):
        """Returns the total liability held by the given account
           corresponding to all the prepaid instruments owned by the
           account.
        """
        return self.get_object(action, {}, response)

    @api_action()
    def get_account_balance(self, action, response):
        """Returns the account balance for an account in real time.
        """
        return self.get_object(action, {}, response)

    @needs_caller_reference
    @requires(['PaymentInstruction', 'TokenType'])
    @api_action()
    def install_payment_instruction(self, action, response, **kw):
        """Installs a payment instruction for caller.
        """
        return self.get_object(action, kw, response)

    @needs_caller_reference
    @requires(['returnURL', 'pipelineName'])
    def cbui_url(self, **kw):
        """Generate a signed URL for the Co-Branded service API given
           arguments as payload.
        """
        sandbox = 'sandbox' in self.host and 'payments-sandbox' or 'payments'
        endpoint = 'authorize.{0}.amazon.com'.format(sandbox)
        base = '/cobranded-ui/actions/start'

        validpipelines = ('SingleUse', 'MultiUse', 'Recurring', 'Recipient',
                          'SetupPrepaid', 'SetupPostpaid', 'EditToken')
        assert kw['pipelineName'] in validpipelines, "Invalid pipelineName"
        kw.update({
            'signatureMethod':  'HmacSHA256',
            'signatureVersion': '2',
        })
        kw.setdefault('callerKey', self.aws_access_key_id)

        safestr = lambda x: x is not None and str(x) or ''
        safequote = lambda x: urllib.quote(safestr(x), safe='~')
        payload = sorted([(k, safequote(v)) for k, v in kw.items()])

        encoded = lambda p: '&'.join([k + '=' + v for k, v in p])
        canonical = '\n'.join(['GET', endpoint, base, encoded(payload)])
        signature = self._auth_handler.sign_string(canonical)
        payload += [('signature', safequote(signature))]
        payload.sort()

        return 'https://{0}{1}?{2}'.format(endpoint, base, encoded(payload))

    @needs_caller_reference
    @complex_amounts('TransactionAmount')
    @requires(['SenderTokenId', 'TransactionAmount.Value',
                                'TransactionAmount.CurrencyCode'])
    @api_action()
    def reserve(self, action, response, **kw):
        """Reserve API is part of the Reserve and Settle API conjunction
           that serve the purpose of a pay where the authorization and
           settlement have a timing difference.
        """
        return self.get_object(action, kw, response)

    @needs_caller_reference
    @complex_amounts('TransactionAmount')
    @requires(['SenderTokenId', 'TransactionAmount.Value',
                                'TransactionAmount.CurrencyCode'])
    @api_action()
    def pay(self, action, response, **kw):
        """Allows calling applications to move money from a sender to
           a recipient.
        """
        return self.get_object(action, kw, response)

    @requires(['TransactionId'])
    @api_action()
    def cancel(self, action, response, **kw):
        """Cancels an ongoing transaction and puts it in cancelled state.
        """
        return self.get_object(action, kw, response)

    @complex_amounts('TransactionAmount')
    @requires(['ReserveTransactionId', 'TransactionAmount.Value',
                                       'TransactionAmount.CurrencyCode'])
    @api_action()
    def settle(self, action, response, **kw):
        """The Settle API is used in conjunction with the Reserve API and
           is used to settle previously reserved transaction.
        """
        return self.get_object(action, kw, response)

    @complex_amounts('RefundAmount')
    @requires(['TransactionId',   'RefundAmount.Value',
               'CallerReference', 'RefundAmount.CurrencyCode'])
    @api_action()
    def refund(self, action, response, **kw):
        """Refunds a previously completed transaction.
        """
        return self.get_object(action, kw, response)

    @requires(['RecipientTokenId'])
    @api_action()
    def get_recipient_verification_status(self, action, response, **kw):
        """Returns the recipient status.
        """
        return self.get_object(action, kw, response)

    @requires(['CallerReference'], ['TokenId'])
    @api_action()
    def get_token_by_caller(self, action, response, **kw):
        """Returns the details of a particular token installed by this
           calling application using the subway co-branded UI.
        """
        return self.get_object(action, kw, response)

    @requires(['UrlEndPoint', 'HttpParameters'])
    @api_action()
    def verify_signature(self, action, response, **kw):
        """Verify the signature that FPS sent in IPN or callback urls.
        """
        return self.get_object(action, kw, response)

    @api_action()
    def get_tokens(self, action, response, **kw):
        """Returns a list of tokens installed on the given account.
        """
        return self.get_object(action, kw, response)

    @requires(['TokenId'])
    @api_action()
    def get_token_usage(self, action, response, **kw):
        """Returns the usage of a token.
        """
        return self.get_object(action, kw, response)

    @requires(['TokenId'])
    @api_action()
    def cancel_token(self, action, response, **kw):
        """Cancels any token installed by the calling application on
           its own account.
        """
        return self.get_object(action, kw, response)

    @needs_caller_reference
    @complex_amounts('FundingAmount')
    @requires(['PrepaidInstrumentId', 'FundingAmount.Value',
               'SenderTokenId',       'FundingAmount.CurrencyCode'])
    @api_action()
    def fund_prepaid(self, action, response, **kw):
        """Funds the prepaid balance on the given prepaid instrument.
        """
        return self.get_object(action, kw, response)

    @requires(['CreditInstrumentId'])
    @api_action()
    def get_debt_balance(self, action, response, **kw):
        """Returns the balance corresponding to the given credit instrument.
        """
        return self.get_object(action, kw, response)

    @needs_caller_reference
    @complex_amounts('AdjustmentAmount')
    @requires(['CreditInstrumentId', 'AdjustmentAmount.Value',
                                     'AdjustmentAmount.CurrencyCode'])
    @api_action()
    def write_off_debt(self, action, response, **kw):
        """Allows a creditor to write off the debt balance accumulated
           partially or fully at any time.
        """
        return self.get_object(action, kw, response)

    @requires(['SubscriptionId'])
    @api_action()
    def get_transactions_for_subscription(self, action, response, **kw):
        """Returns the transactions for a given subscriptionID.
        """
        return self.get_object(action, kw, response)

    @requires(['SubscriptionId'])
    @api_action()
    def get_subscription_details(self, action, response, **kw):
        """Returns the details of Subscription for a given subscriptionID.
        """
        return self.get_object(action, kw, response)

    @needs_caller_reference
    @complex_amounts('RefundAmount')
    @requires(['SubscriptionId'])
    @api_action()
    def cancel_subscription_and_refund(self, action, response, **kw):
        """Cancels a subscription.
        """
        message = "If you specify a RefundAmount, " \
                  "you must specify CallerReference."
        assert not 'RefundAmount.Value' in kw \
                or 'CallerReference' in kw, message
        return self.get_object(action, kw, response)

    @requires(['TokenId'])
    @api_action()
    def get_payment_instruction(self, action, response, **kw):
        """Gets the payment instruction of a token.
        """
        return self.get_object(action, kw, response)
<|endoftext|>


<commit_before># General
DEBUG = False
SECRET_KEY = ''

# DB
SQLALCHEMY_DATABASE_URI = ''
SQLALCHEMY_TRACK_MODIFICATIONS = False

# Mail
MAIL_HOST = ''
MAIL_PORT = ''
MAIL_LOGIN_USER = ''
MAIL_LOGIN_PASS = ''
MAIL_FROM = ''
<commit_msg>Delete config.py<commit_after><|endoftext|>


<commit_before>from . import models
from crispy_forms import layout
from django import forms
from django.contrib import auth
from entities import models as entities_models
from utils import forms as utils_forms

class BaseContent(utils_forms.FormMixin, forms.ModelForm):
    author = forms.ModelChoiceField(disabled=True, queryset=entities_models.Gestalt.objects.all(), widget=forms.HiddenInput)
    pinned = forms.BooleanField(label='Im Intro der Gruppe anheften', required=False)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['group'] = forms.ModelChoiceField(label='Gruppe', queryset=self.get_group_queryset(), required=False)

    def get_group_queryset(self):
        return entities_models.Gestalt.objects.get(pk=self.initial['author']).groups

    def save(self):
        content = super().save()
        if self.cleaned_data['group']:
            entities_models.GroupContent.objects.update_or_create(content=content, group=self.cleaned_data['group'], defaults={'pinned': self.cleaned_data['pinned']})
        else:
            entities_models.GroupContent.objects.filter(content=content).delete()
        return content

class Article(BaseContent):
    layout = ('author', 'group', 'title', utils_forms.EditorField('text'), 'pinned', utils_forms.Submit('Artikel erstellen'))

    class Meta:
        fields = ('author', 'text', 'title')
        model = models.Article

    def __init__(self, *args, **kwargs):
        kwargs['instance'] = models.Article(public=True)
        super().__init__(*args, **kwargs)

class Event(BaseContent):
    layout = ('author', 'group', 'pinned', 'title', layout.Field('time', data_component='date date-datetime'), 'place', utils_forms.EditorField('text'), 'public', utils_forms.Submit('Ereignis erstellen'))

    class Meta:
        fields = ('author', 'place', 'public', 'text', 'time', 'title')
        labels = {'text': 'Beschreibung'}
        model = models.Event

class Gallery(BaseContent):
    layout = ('author', 'group', 'title', utils_forms.EditorField('text'), 'public', 'pinned', utils_forms.Submit('Galerie erstellen'))

    class Meta:
        fields = ('author', 'public', 'text', 'title')
        labels = {'text': 'Beschreibung'}
        model = models.Gallery

class BaseMessage(utils_forms.FormMixin, forms.ModelForm):
    layout = ('recipient', 'sender', 'title', utils_forms.EditorField('text'), utils_forms.Submit('Nachricht senden'))
    sender = forms.EmailField(label='E-Mail-Adresse')

    class Meta:
        fields = ('text', 'title')
        labels = {'text': 'Nachricht', 'title': 'Betreff'}
        model = models.Article

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['recipient'] = forms.ModelChoiceField(disabled=True, label='Empfängerin', queryset=self.get_recipient_queryset(), widget=forms.HiddenInput)
        if self.initial.get('sender'):
            self.fields['sender'].disabled = True
            self.fields['sender'].widget = forms.HiddenInput

    def clean(self):
        if not self.fields['sender'].disabled:
            try:
                auth.get_user_model().objects.get(email=self.cleaned_data['sender'])
                if True: # TODO password is usable
                    self.add_error('sender', forms.ValidationError('Es gibt bereits ein Benutzerkonto mit dieser E-Mail-Adresse. Bitte melde Dich mit E-Mail-Adresse und Kennwort an.', code='existing'))
            except auth.get_user_model().DoesNotExist:
                pass
        return super().clean()

    def save(self):
        message = super().save(commit=False)
        auth.get_user_model().objects.get_or_create(email=self.cleaned_data['sender'])
        message.author = entities_models.Gestalt.objects.get(user__email=self.cleaned_data['sender'])
        message.save()
        return message

class GestaltMessage(BaseMessage):
    def get_recipient_queryset(self):
        return entities_models.Gestalt.objects.all()

    def save(self):
        message = super().save()
        entities_models.GestaltContent.objects.create(content=message, gestalt=self.cleaned_data['recipient'])

class GroupMessage(BaseMessage):
    def get_recipient_queryset(self):
        return entities_models.Group.objects.all()

    def save(self):
        message = super().save()
        entities_models.GroupContent.objects.create(content=message, group=self.cleaned_data['recipient'])

class ContentUpdate(utils_forms.FormMixin, forms.ModelForm):
    class Meta:
        fields = ('text', 'title')
        model = models.Content

    def __init__(self, *args, **kwargs):
        self.groupcontent = kwargs.pop('groupcontent', None)
        super().__init__(*args, **kwargs)
        if self.groupcontent:
            self.fields['pinned'] = forms.BooleanField(label='Im Intro der Gruppe anheften', required=False)
            self.initial['pinned'] = self.groupcontent.pinned

    def get_layout(self):
        fields = layout.Layout('title', utils_forms.EditorField('text'), utils_forms.Submit('Beitrag ändern'))
        if self.groupcontent:
            fields.insert(-1, 'pinned')
        return fields

    def save(self):
        if self.groupcontent:
            self.groupcontent.pinned = self.cleaned_data['pinned']
            self.groupcontent.save()
        return super().save()
<commit_msg>Add username and unusable password<commit_after>from . import models
from allauth.account import adapter as allauth_adapter
from crispy_forms import layout
from django import forms
from django.contrib import auth
from entities import models as entities_models
from utils import forms as utils_forms

class BaseContent(utils_forms.FormMixin, forms.ModelForm):
    author = forms.ModelChoiceField(disabled=True, queryset=entities_models.Gestalt.objects.all(), widget=forms.HiddenInput)
    pinned = forms.BooleanField(label='Im Intro der Gruppe anheften', required=False)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['group'] = forms.ModelChoiceField(label='Gruppe', queryset=self.get_group_queryset(), required=False)

    def get_group_queryset(self):
        return entities_models.Gestalt.objects.get(pk=self.initial['author']).groups

    def save(self):
        content = super().save()
        if self.cleaned_data['group']:
            entities_models.GroupContent.objects.update_or_create(content=content, group=self.cleaned_data['group'], defaults={'pinned': self.cleaned_data['pinned']})
        else:
            entities_models.GroupContent.objects.filter(content=content).delete()
        return content

class Article(BaseContent):
    layout = ('author', 'group', 'title', utils_forms.EditorField('text'), 'pinned', utils_forms.Submit('Artikel erstellen'))

    class Meta:
        fields = ('author', 'text', 'title')
        model = models.Article

    def __init__(self, *args, **kwargs):
        kwargs['instance'] = models.Article(public=True)
        super().__init__(*args, **kwargs)

class Event(BaseContent):
    layout = ('author', 'group', 'pinned', 'title', layout.Field('time', data_component='date date-datetime'), 'place', utils_forms.EditorField('text'), 'public', utils_forms.Submit('Ereignis erstellen'))

    class Meta:
        fields = ('author', 'place', 'public', 'text', 'time', 'title')
        labels = {'text': 'Beschreibung'}
        model = models.Event

class Gallery(BaseContent):
    layout = ('author', 'group', 'title', utils_forms.EditorField('text'), 'public', 'pinned', utils_forms.Submit('Galerie erstellen'))

    class Meta:
        fields = ('author', 'public', 'text', 'title')
        labels = {'text': 'Beschreibung'}
        model = models.Gallery

class BaseMessage(utils_forms.FormMixin, forms.ModelForm):
    layout = ('recipient', 'sender', 'title', utils_forms.EditorField('text'), utils_forms.Submit('Nachricht senden'))
    sender = forms.EmailField(label='E-Mail-Adresse')

    class Meta:
        fields = ('text', 'title')
        labels = {'text': 'Nachricht', 'title': 'Betreff'}
        model = models.Article

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['recipient'] = forms.ModelChoiceField(disabled=True, label='Empfängerin', queryset=self.get_recipient_queryset(), widget=forms.HiddenInput)
        if self.initial.get('sender'):
            self.fields['sender'].disabled = True
            self.fields['sender'].widget = forms.HiddenInput

    def clean(self):
        if not self.fields['sender'].disabled:
            try:
                user = auth.get_user_model().objects.get(email=self.cleaned_data['sender'])
                if user.has_usable_password():
                    self.add_error('sender', forms.ValidationError('Es gibt bereits ein Benutzerkonto mit dieser E-Mail-Adresse. Bitte melde Dich mit E-Mail-Adresse und Kennwort an.', code='existing'))
            except auth.get_user_model().DoesNotExist:
                pass
        return super().clean()

    def save(self):
        message = super().save(commit=False)
        user, created = auth.get_user_model().objects.get_or_create(email=self.cleaned_data['sender'])
        if created:
            allauth_adapter.get_adapter().populate_username(None, user)
            user.set_unusable_password()
            user.save()
        message.author = entities_models.Gestalt.objects.get(user__email=self.cleaned_data['sender'])
        message.save()
        return message

class GestaltMessage(BaseMessage):
    def get_recipient_queryset(self):
        return entities_models.Gestalt.objects.all()

    def save(self):
        message = super().save()
        entities_models.GestaltContent.objects.create(content=message, gestalt=self.cleaned_data['recipient'])

class GroupMessage(BaseMessage):
    def get_recipient_queryset(self):
        return entities_models.Group.objects.all()

    def save(self):
        message = super().save()
        entities_models.GroupContent.objects.create(content=message, group=self.cleaned_data['recipient'])

class ContentUpdate(utils_forms.FormMixin, forms.ModelForm):
    class Meta:
        fields = ('text', 'title')
        model = models.Content

    def __init__(self, *args, **kwargs):
        self.groupcontent = kwargs.pop('groupcontent', None)
        super().__init__(*args, **kwargs)
        if self.groupcontent:
            self.fields['pinned'] = forms.BooleanField(label='Im Intro der Gruppe anheften', required=False)
            self.initial['pinned'] = self.groupcontent.pinned

    def get_layout(self):
        fields = layout.Layout('title', utils_forms.EditorField('text'), utils_forms.Submit('Beitrag ändern'))
        if self.groupcontent:
            fields.insert(-1, 'pinned')
        return fields

    def save(self):
        if self.groupcontent:
            self.groupcontent.pinned = self.cleaned_data['pinned']
            self.groupcontent.save()
        return super().save()
<|endoftext|>


<commit_before>import optparse

from django.core.management import base as management_base
from django.utils import importlib

from ... import document as itsy_document
from ... import tasks as itsy_tasks

class Command(management_base.BaseCommand):
  args = "class_path"
  help = "Performs a reindex of the given document class."
  requires_model_validation = True
  option_list = management_base.BaseCommand.option_list + (
    optparse.make_option('--background', action = 'store_true', dest = 'background', default = False,
      help = "Should the reindexing be performed by background workers."),

    optparse.make_option('--recreate-index', action = 'store_true', dest = 'recreate-index', default = False,
      help = "Should the index be dropped and recreated. THIS WILL ERASE ALL DATA!")
  )

  def handle(self, *args, **options):
    """
    Performs a reindex of the given document class.
    """
    if len(args) != 1:
      raise management_base.CommandError("Reindex command takes exactly one argument!")

    # Load the specified document class
    class_path = args[0]
    module_name = class_path[:class_path.rfind(".")]
    class_name = class_path[class_path.rfind(".") + 1:]
    module = importlib.import_module(module_name)
    document_class = getattr(module, class_name)

    if not issubclass(document_class, itsy_document.Document):
      raise management_base.CommandError("Specified class is not a valid Document!")

    if options.get("recreate-index"):
      # Drop the index and recreate it
      self.stdout.write("Recreating index...\n")
      document_class._meta.search_engine.drop()
      document_class._meta.emit_search_mappings()

    if options.get("background"):
      # Spawn the reindex task
      itsy_tasks.search_index_reindex.delay(document_class)

      # Notify the user that the reindex has started in the background
      self.stdout.write("Reindex of %s has been initiated in the background.\n" % class_path)
    else:
      self.stdout.write("Performing foreground reindex of %s...\n" % class_path)
      itsy_tasks.search_index_reindex(document_class)
<commit_msg>Check that the document class to be reindexed is actually searchable.<commit_after>import optparse

from django.core.management import base as management_base
from django.utils import importlib

from ... import document as itsy_document
from ... import tasks as itsy_tasks

class Command(management_base.BaseCommand):
  args = "class_path"
  help = "Performs a reindex of the given document class."
  requires_model_validation = True
  option_list = management_base.BaseCommand.option_list + (
    optparse.make_option('--background', action = 'store_true', dest = 'background', default = False,
      help = "Should the reindexing be performed by background workers."),

    optparse.make_option('--recreate-index', action = 'store_true', dest = 'recreate-index', default = False,
      help = "Should the index be dropped and recreated. THIS WILL ERASE ALL DATA!")
  )

  def handle(self, *args, **options):
    """
    Performs a reindex of the given document class.
    """
    if len(args) != 1:
      raise management_base.CommandError("Reindex command takes exactly one argument!")

    # Load the specified document class
    class_path = args[0]
    module_name = class_path[:class_path.rfind(".")]
    class_name = class_path[class_path.rfind(".") + 1:]
    module = importlib.import_module(module_name)
    document_class = getattr(module, class_name)

    if not issubclass(document_class, itsy_document.Document):
      raise management_base.CommandError("Specified class is not a valid Document!")

    if not document_class._meta.searchable or document_class._meta.abstract or document_class._meta.embedded:
      raise management_base.CommandError("Specified document is not searchable!")

    if options.get("recreate-index"):
      # Drop the index and recreate it
      self.stdout.write("Recreating index...\n")
      document_class._meta.search_engine.drop()
      document_class._meta.emit_search_mappings()

    if options.get("background"):
      # Spawn the reindex task
      itsy_tasks.search_index_reindex.delay(document_class)

      # Notify the user that the reindex has started in the background
      self.stdout.write("Reindex of %s has been initiated in the background.\n" % class_path)
    else:
      self.stdout.write("Performing foreground reindex of %s...\n" % class_path)
      itsy_tasks.search_index_reindex(document_class)
<|endoftext|>


<commit_before>from django.conf import settings
from django.conf.urls import include, patterns, url

from django.contrib import admin
admin.autodiscover()

from big_projects_watch.urls import urlpatterns

if settings.DEBUG:
    urlpatterns += patterns('',
        url(r'^admin/', include(admin.site.urls)),
        url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
            'document_root': settings.MEDIA_ROOT,
        }),
    )<commit_msg>Wrong integration of admin url in urls.py<commit_after>from django.conf import settings
from django.conf.urls import include, patterns, url

from django.contrib import admin
admin.autodiscover()

from big_projects_watch.urls import urlpatterns

urlpatterns += patterns('',
    url(r'^admin/', include(admin.site.urls)),
)

if settings.DEBUG:
    urlpatterns += patterns('',
        url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
            'document_root': settings.MEDIA_ROOT,
        }),
    )<|endoftext|>


<commit_before>from django.contrib import admin
import api.models as models
from ajax_select import make_ajax_form
from ajax_select.admin import AjaxSelectAdmin

@admin.register(models.Application)
class ApplicationAdmin(admin.ModelAdmin):
    list_display = ('__str__', 'key', 'active')

@admin.register(models.RelationFractionASTM)
class ApplicationAdmin(AjaxSelectAdmin):
    form = make_ajax_form(models.RelationFractionASTM, {
        'fraction': 'fraction'
    })

@admin.register(models.Analyzer)
class ApplicationAdmin(AjaxSelectAdmin):
    list_display = ('__str__', 'protocol', 'mode', 'connection_string')
<commit_msg>Upgrade to Django 2.0<commit_after>from django.contrib import admin
import api.models as models
from ajax_select import make_ajax_form
from ajax_select.admin import AjaxSelectAdmin

@admin.register(models.Application)
class ApplicationAdmin(admin.ModelAdmin):
    list_display = ('__str__', 'key', 'active')

admin.site.register(models.RelationFractionASTM)

@admin.register(models.Analyzer)
class ApplicationAdmin(AjaxSelectAdmin):
    list_display = ('__str__', 'protocol', 'mode', 'connection_string')
<|endoftext|>


<commit_before>try:
    import cPickle as pickle
except ImportError:
    import pickle

import hashlib, os, os.path
from datetime import datetime
from django.conf import settings
from models import GeneratedMap
from draw import get_map, get_fitted_map

MARKER_COLORS = (
#    ('blue', '#0000ff', '#000050', '#ffffff'),
#    ('red', '#ff0000', '#500000', '#ffffff'),
#    ('yellow', '#f0ff00', '#4b5000', '#000000'),
#    ('green', '#00ff1e', '#005009', '#000000'),
    ('purple', '#9146b8', '#3c1d4c', '#ffffff'),
#    ('amber', '#ff7e00', '#824000', '#000000'),
)

MARKER_RANGE = xrange(1, 100)

def get_or_create_map(f, args):
    hash = hashlib.sha224(pickle.dumps(repr(args))).hexdigest()[:16]

    try:
        gm = GeneratedMap.objects.get(hash=hash)
        gm.last_accessed = datetime.utcnow()
        gm.save()
        metadata = gm.metadata
    except GeneratedMap.DoesNotExist:
        if not os.path.exists(settings.GENERATED_MAP_DIR):
            os.makedirs(settings.GENERATED_MAP_DIR)
        metadata = f(filename=os.path.join(settings.GENERATED_MAP_DIR, hash), *args)
        gm = GeneratedMap(
            hash = hash,
            generated = datetime.utcnow(),
            last_accessed = datetime.utcnow(),
        )
        gm.metadata = metadata
        gm.save()
    return hash, metadata

def get_generated_map(points, width, height):
    return get_or_create_map(get_map, (points, width, height))

def fit_to_map(centre_point, points, min_points, zoom, width, height):
    points = list(points)
    return get_or_create_map(get_fitted_map, (centre_point, points, min_points, zoom, width, height))
<commit_msg>Uncommented commented out marker colours<commit_after>try:
    import cPickle as pickle
except ImportError:
    import pickle

import hashlib, os, os.path
from datetime import datetime
from django.conf import settings
from models import GeneratedMap
from draw import get_map, get_fitted_map

MARKER_COLORS = (
    ('blue', '#0000ff', '#000050', '#ffffff'),
    ('red', '#ff0000', '#500000', '#ffffff'),
    ('yellow', '#f0ff00', '#4b5000', '#000000'),
    ('green', '#00ff1e', '#005009', '#000000'),
    ('purple', '#9146b8', '#3c1d4c', '#ffffff'),
    ('amber', '#ff7e00', '#824000', '#000000'),
)

MARKER_RANGE = xrange(1, 100)

def get_or_create_map(f, args):
    hash = hashlib.sha224(pickle.dumps(repr(args))).hexdigest()[:16]

    try:
        gm = GeneratedMap.objects.get(hash=hash)
        gm.last_accessed = datetime.utcnow()
        gm.save()
        metadata = gm.metadata
    except GeneratedMap.DoesNotExist:
        if not os.path.exists(settings.GENERATED_MAP_DIR):
            os.makedirs(settings.GENERATED_MAP_DIR)
        metadata = f(filename=os.path.join(settings.GENERATED_MAP_DIR, hash), *args)
        gm = GeneratedMap(
            hash = hash,
            generated = datetime.utcnow(),
            last_accessed = datetime.utcnow(),
        )
        gm.metadata = metadata
        gm.save()
    return hash, metadata

def get_generated_map(points, width, height):
    return get_or_create_map(get_map, (points, width, height))

def fit_to_map(centre_point, points, min_points, zoom, width, height):
    points = list(points)
    return get_or_create_map(get_fitted_map, (centre_point, points, min_points, zoom, width, height))
<|endoftext|>


<commit_before># Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
import re
import sys
import os

from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style
from .winterm import WinTerm, WinColor, WinStyle
from .win32 import windll, winapi_test

winterm = None
if windll is not None:
    winterm = WinTerm()

def is_stream_closed(stream):
    return not hasattr(stream, 'closed') or stream.closed

def is_a_tty(stream):
    return hasattr(stream, 'isatty') and stream.isatty()

class StreamWrapper(object):
    '''
    Wraps a stream (such as stdout), acting as a transparent proxy for all
    attribute access apart from method 'write()', which is delegated to our
    Converter instance.
    '''
    def __init__(self, wrapped, converter):
        # double-underscore everything to prevent clashes with names of
        # attributes on the wrapped stream object.
        self.__wrapped = wrapped
        self.__convertor = converter

    def __getattr__(self, name):
        return getattr(self.__wrapped, name)

    def write(self, text):
        self.__convertor.write(text)

class AnsiToWin32(object):
    '''
    Implements a 'write()' method which, on Windows, will strip ANSI character
    sequences from the text, and if outputting to a tty, will convert them into
    win32 function calls.
    '''
    ANSI_CSI_RE = re.compile('\001?\033\[((?:\d|;)*)([a-zA-Z])\002?')     # Control Sequence Introducer
    ANSI_OSC_RE = re.compile('\001?\033\]((?:.|;)*?)(\x07)\002?')         # Operating System Command

    def __init__(self, wrapped, convert=None, strip=None, autoreset=False):
        # The wrapped stream (normally sys.stdout or sys.stderr)
        self.wrapped = wrapped

        # should we reset colors to defaults after every .write()
        self.autoreset = autoreset

        # create the proxy wrapping our output stream
        self.stream = StreamWrapper(wrapped, self)

        on_windows = os.name == 'nt'
        # We test if the WinAPI works, because even if we are on Windows
        # we may be using a terminal that doesn't support the WinAPI
        # (e.g. Cygwin Terminal). In this case it's up to the terminal
        # to support the ANSI codes.
        conversion_supported = on_windows and winapi_test()

        # should we strip ANSI sequences from our output?
        if strip is None:
            strip = conversion_supported or (not is_stream_closed(wrapped) and not is_a_tty(wrapped))
        self.strip = strip

        # should we should convert ANSI sequences into win32 calls?
        if convert is None:
            convert = conversion_supported and not is_stream_closed(wrapped) and is_a_tty(wrapped)
        self.convert = convert

        # dict of ansi codes to win32 functions and parameters
        self.win32_calls = self.get_win32_calls()

        # are we wrapping stderr?
        self.on_stderr = self.wrapped is sys.stderr

    def should_wrap(self):
        '''
        True if this class is actually needed. If false, then the output
        stream will not be affected, nor will win32 calls be issued, so
        wrapping stdout is not actually required. This will generally be
        False on non-Windows platforms, unless optional functionality like
        autoreset has been requested using kwargs to init()
        '''
        return self.convert or self.strip or self.autoreset

    def get_win32_calls(self):
        if self.convert and winterm:
            return {
                AnsiStyle.RESET_ALL: (winterm.reset_all, ),
                AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT),
                AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL),
                AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL),
                AnsiFore.BLACK: (winterm.fore, WinColor.BLACK),
                AnsiFore.RED: (winterm.fore, WinColor.RED),
                AnsiFore.GREEN: (winterm.fore, WinColor.GREEN),
                AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW),
                AnsiFore.BLUE: (winterm.fore, WinColor.BLUE),
                AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA),
                AnsiFore.CYAN: (winterm.fore, WinColor.CYAN),
                AnsiFore.WHITE: (winterm.fore, WinColor.GREY),
                AnsiFore.RESET: (winterm.fore, ),
                AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True),
                AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True),
                AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True),
                AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True),
                AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True),
                AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True),
                AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True),
                AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True),
                AnsiBack.BLACK: (winterm.back, WinColor.BLACK),
                AnsiBack.RED: (winterm.back, WinColor.RED),
                AnsiBack.GREEN: (winterm.back, WinColor.GREEN),
                AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW),
                AnsiBack.BLUE: (winterm.back, WinColor.BLUE),
                AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA),
                AnsiBack.CYAN: (winterm.back, WinColor.CYAN),
                AnsiBack.WHITE: (winterm.back, WinColor.GREY),
                AnsiBack.RESET: (winterm.back, ),
                AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True),
                AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True),
                AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True),
                AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True),
                AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True),
                AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True),
                AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True),
                AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True),
            }
        return dict()

    def write(self, text):
        if self.strip or self.convert:
            self.write_and_convert(text)
        else:
            self.wrapped.write(text)
            self.wrapped.flush()
        if self.autoreset:
            self.reset_all()

    def reset_all(self):
        if self.convert:
            self.call_win32('m', (0,))
        elif not self.strip and not is_stream_closed(self.wrapped):
            self.wrapped.write(Style.RESET_ALL)

    def write_and_convert(self, text):
        '''
        Write the given text to our wrapped stream, stripping any ANSI
        sequences from the text, and optionally converting them into win32
        calls.
        '''
        cursor = 0
        text = self.convert_osc(text)
        for match in self.ANSI_CSI_RE.finditer(text):
            start, end = match.span()
            self.write_plain_text(text, cursor, start)
            self.convert_ansi(*match.groups())
            cursor = end
        self.write_plain_text(text, cursor, len(text))

    def write_plain_text(self, text, start, end):
        if start < end:
            self.wrapped.write(text[start:end])
            self.wrapped.flush()

    def convert_ansi(self, paramstring, command):
        if self.convert:
            params = self.extract_params(command, paramstring)
            self.call_win32(command, params)

    def extract_params(self, command, paramstring):
        if command in 'Hf':
            params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';'))
            while len(params) < 2:
                # defaults:
                params = params + (1,)
        else:
            params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0)
            if len(params) == 0:
                # defaults:
                if command in 'JKm':
                    params = (0,)
                elif command in 'ABCD':
                    params = (1,)

        return params

    def call_win32(self, command, params):
        if command == 'm':
            for param in params:
                if param in self.win32_calls:
                    func_args = self.win32_calls[param]
                    func = func_args[0]
                    args = func_args[1:]
                    kwargs = dict(on_stderr=self.on_stderr)
                    func(*args, **kwargs)
        elif command in 'J':
            winterm.erase_screen(params[0], on_stderr=self.on_stderr)
        elif command in 'K':
            winterm.erase_line(params[0], on_stderr=self.on_stderr)
        elif command in 'Hf':     # cursor position - absolute
            winterm.set_cursor_position(params, on_stderr=self.on_stderr)
        elif command in 'ABCD':   # cursor position - relative
            n = params[0]
            # A - up, B - down, C - forward, D - back
            x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command]
            winterm.cursor_adjust(x, y, on_stderr=self.on_stderr)

    def convert_osc(self, text):
        for match in self.ANSI_OSC_RE.finditer(text):
            start, end = match.span()
            text = text[:start] + text[end:]
            paramstring, command = match.groups()
            if command in '\x07':       # \x07 = BEL
                params = paramstring.split(";")
                # 0 - change title and icon (we will only change title)
                # 1 - change icon (we don't support this)
                # 2 - change title
                if params[0] in '02':
                    winterm.set_title(params[1])
        return text
<commit_msg>Fix issue #103 - work around Python bug in input function<commit_after># Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
import re
import sys
import os

from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style
from .winterm import WinTerm, WinColor, WinStyle
from .win32 import windll, winapi_test

winterm = None
if windll is not None:
    winterm = WinTerm()

def is_stream_closed(stream):
    return not hasattr(stream, 'closed') or stream.closed

def is_a_tty(stream):
    return hasattr(stream, 'isatty') and stream.isatty()

class StreamWrapper(object):
    '''
    Wraps a stream (such as stdout), acting as a transparent proxy for all
    attribute access apart from method 'write()', which is delegated to our
    Converter instance.
    '''
    def __init__(self, wrapped, converter):
        # double-underscore everything to prevent clashes with names of
        # attributes on the wrapped stream object.
        self.__wrapped = wrapped
        self.__convertor = converter

    def __getattr__(self, name):
        return getattr(self.__wrapped, name)

    def write(self, text):
        self.__convertor.write(text)

    def fileno():
        raise OSError()

class AnsiToWin32(object):
    '''
    Implements a 'write()' method which, on Windows, will strip ANSI character
    sequences from the text, and if outputting to a tty, will convert them into
    win32 function calls.
    '''
    ANSI_CSI_RE = re.compile('\001?\033\[((?:\d|;)*)([a-zA-Z])\002?')     # Control Sequence Introducer
    ANSI_OSC_RE = re.compile('\001?\033\]((?:.|;)*?)(\x07)\002?')         # Operating System Command

    def __init__(self, wrapped, convert=None, strip=None, autoreset=False):
        # The wrapped stream (normally sys.stdout or sys.stderr)
        self.wrapped = wrapped

        # should we reset colors to defaults after every .write()
        self.autoreset = autoreset

        # create the proxy wrapping our output stream
        self.stream = StreamWrapper(wrapped, self)

        on_windows = os.name == 'nt'
        # We test if the WinAPI works, because even if we are on Windows
        # we may be using a terminal that doesn't support the WinAPI
        # (e.g. Cygwin Terminal). In this case it's up to the terminal
        # to support the ANSI codes.
        conversion_supported = on_windows and winapi_test()

        # should we strip ANSI sequences from our output?
        if strip is None:
            strip = conversion_supported or (not is_stream_closed(wrapped) and not is_a_tty(wrapped))
        self.strip = strip

        # should we should convert ANSI sequences into win32 calls?
        if convert is None:
            convert = conversion_supported and not is_stream_closed(wrapped) and is_a_tty(wrapped)
        self.convert = convert

        # dict of ansi codes to win32 functions and parameters
        self.win32_calls = self.get_win32_calls()

        # are we wrapping stderr?
        self.on_stderr = self.wrapped is sys.stderr

    def should_wrap(self):
        '''
        True if this class is actually needed. If false, then the output
        stream will not be affected, nor will win32 calls be issued, so
        wrapping stdout is not actually required. This will generally be
        False on non-Windows platforms, unless optional functionality like
        autoreset has been requested using kwargs to init()
        '''
        return self.convert or self.strip or self.autoreset

    def get_win32_calls(self):
        if self.convert and winterm:
            return {
                AnsiStyle.RESET_ALL: (winterm.reset_all, ),
                AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT),
                AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL),
                AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL),
                AnsiFore.BLACK: (winterm.fore, WinColor.BLACK),
                AnsiFore.RED: (winterm.fore, WinColor.RED),
                AnsiFore.GREEN: (winterm.fore, WinColor.GREEN),
                AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW),
                AnsiFore.BLUE: (winterm.fore, WinColor.BLUE),
                AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA),
                AnsiFore.CYAN: (winterm.fore, WinColor.CYAN),
                AnsiFore.WHITE: (winterm.fore, WinColor.GREY),
                AnsiFore.RESET: (winterm.fore, ),
                AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True),
                AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True),
                AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True),
                AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True),
                AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True),
                AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True),
                AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True),
                AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True),
                AnsiBack.BLACK: (winterm.back, WinColor.BLACK),
                AnsiBack.RED: (winterm.back, WinColor.RED),
                AnsiBack.GREEN: (winterm.back, WinColor.GREEN),
                AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW),
                AnsiBack.BLUE: (winterm.back, WinColor.BLUE),
                AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA),
                AnsiBack.CYAN: (winterm.back, WinColor.CYAN),
                AnsiBack.WHITE: (winterm.back, WinColor.GREY),
                AnsiBack.RESET: (winterm.back, ),
                AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True),
                AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True),
                AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True),
                AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True),
                AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True),
                AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True),
                AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True),
                AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True),
            }
        return dict()

    def write(self, text):
        if self.strip or self.convert:
            self.write_and_convert(text)
        else:
            self.wrapped.write(text)
            self.wrapped.flush()
        if self.autoreset:
            self.reset_all()

    def reset_all(self):
        if self.convert:
            self.call_win32('m', (0,))
        elif not self.strip and not is_stream_closed(self.wrapped):
            self.wrapped.write(Style.RESET_ALL)

    def write_and_convert(self, text):
        '''
        Write the given text to our wrapped stream, stripping any ANSI
        sequences from the text, and optionally converting them into win32
        calls.
        '''
        cursor = 0
        text = self.convert_osc(text)
        for match in self.ANSI_CSI_RE.finditer(text):
            start, end = match.span()
            self.write_plain_text(text, cursor, start)
            self.convert_ansi(*match.groups())
            cursor = end
        self.write_plain_text(text, cursor, len(text))

    def write_plain_text(self, text, start, end):
        if start < end:
            self.wrapped.write(text[start:end])
            self.wrapped.flush()

    def convert_ansi(self, paramstring, command):
        if self.convert:
            params = self.extract_params(command, paramstring)
            self.call_win32(command, params)

    def extract_params(self, command, paramstring):
        if command in 'Hf':
            params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';'))
            while len(params) < 2:
                # defaults:
                params = params + (1,)
        else:
            params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0)
            if len(params) == 0:
                # defaults:
                if command in 'JKm':
                    params = (0,)
                elif command in 'ABCD':
                    params = (1,)

        return params

    def call_win32(self, command, params):
        if command == 'm':
            for param in params:
                if param in self.win32_calls:
                    func_args = self.win32_calls[param]
                    func = func_args[0]
                    args = func_args[1:]
                    kwargs = dict(on_stderr=self.on_stderr)
                    func(*args, **kwargs)
        elif command in 'J':
            winterm.erase_screen(params[0], on_stderr=self.on_stderr)
        elif command in 'K':
            winterm.erase_line(params[0], on_stderr=self.on_stderr)
        elif command in 'Hf':     # cursor position - absolute
            winterm.set_cursor_position(params, on_stderr=self.on_stderr)
        elif command in 'ABCD':   # cursor position - relative
            n = params[0]
            # A - up, B - down, C - forward, D - back
            x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command]
            winterm.cursor_adjust(x, y, on_stderr=self.on_stderr)

    def convert_osc(self, text):
        for match in self.ANSI_OSC_RE.finditer(text):
            start, end = match.span()
            text = text[:start] + text[end:]
            paramstring, command = match.groups()
            if command in '\x07':       # \x07 = BEL
                params = paramstring.split(";")
                # 0 - change title and icon (we will only change title)
                # 1 - change icon (we don't support this)
                # 2 - change title
                if params[0] in '02':
                    winterm.set_title(params[1])
        return text
<|endoftext|>


<commit_before>import os

# from azure.storage import BlobService

def store(*args):
    pass

def retrieve(*args):
    pass

# def store(image, entity, entity_id):
#     blob_service = BlobService(account_name='shnergledata',
#                                account_key=os.environ['BLOB_KEY'])
#     myblob = image.read()
#     name = '/' + entity + '/' + entity_id
#     blob_service.put_blob('images', name, myblob, x_ms_blob_type='BlockBlob')
#     return True
#
#
# def retrieve(entity, entity_id):
#     blob_service = BlobService(account_name='shnergledata',
#                                account_key=os.environ['BLOB_KEY'])
#     name = '/' + entity + '/' + entity_id
#     blob = blob_service.get_blob('images', name)
#     return blob
<commit_msg>My code good, MS bad<commit_after>import os

from azure.storage import BlobService

def store(image, entity, entity_id):
    blob_service = BlobService(account_name='shnergledata',
                               account_key=os.environ['BLOB_KEY'])
    myblob = image.read()
    name = '/' + entity + '/' + entity_id
    blob_service.put_blob('images', name, myblob, x_ms_blob_type='BlockBlob')
    return True

def retrieve(entity, entity_id):
    blob_service = BlobService(account_name='shnergledata',
                               account_key=os.environ['BLOB_KEY'])
    name = '/' + entity + '/' + entity_id
    blob = blob_service.get_blob('images', name)
    return blob
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
Colour - HDRI
=============

HDRI - Radiance image processing algorithms for *Python*.

Subpackages
-----------
-   calibration: Camera calibration computations.
-   examples: Examples for the sub-packages.
-   generation: HDRI / radiance image generation.
-   models: Colour models conversion.
-   plotting: Diagrams, figures, etc...
-   process: Image conversion helpers.
-   recovery: Clipped highlights recovery.
-   resources: Resources sub-modules.
-   sampling: Image sampling routines.
-   tonemapping: Tonemapping operators.
-   utilities: Various utilities and data structures.
"""

from __future__ import absolute_import

import numpy as np
import os
import recordclass
import subprocess

import colour

from .utilities import (
    EXIF_EXECUTABLE, ExifTag, adjust_exposure, average_luminance,
    copy_exif_tags, delete_exif_tags, exposure_value, filter_files, Image,
    ImageStack, Metadata, parse_exif_array, parse_exif_data,
    parse_exif_fraction, parse_exif_numeric, parse_exif_string, path_exists,
    read_exif_tag, read_exif_tags, update_exif_tags, vivification,
    vivified_to_dict, write_exif_tag)
from .sampling import (
    light_probe_sampling_variance_minimization_Viriyothai2009,
    samples_Grossberg2003)
from .generation import (normal_distribution_function, hat_function,
                         weighting_function_Debevec1997,
                         image_stack_to_radiance_image)
from .calibration import (absolute_luminance_calibration_Lagarde2016,
                          camera_response_functions_Debevec1997, g_solve,
                          upper_hemisphere_illuminance_weights_Lagarde2016)
from .models import (camera_neutral_to_xy, camera_space_to_RGB,
                     camera_space_to_sRGB, camera_space_to_XYZ_matrix,
                     xy_to_camera_neutral, XYZ_to_camera_space_matrix)
from .process import (DNG_CONVERSION_ARGUMENTS, DNG_CONVERTER,
                      DNG_EXIF_TAGS_BINDING, RAW_CONVERSION_ARGUMENTS,
                      RAW_CONVERTER, RAW_D_CONVERSION_ARGUMENTS,
                      convert_dng_files_to_intermediate_files,
                      convert_raw_files_to_dng_files, read_dng_files_exif_tags)
from .recovery import (highlights_recovery_blend, highlights_recovery_LCHab)
from .tonemapping import (
    tonemapping_operator_exponential,
    tonemapping_operator_exponentiation_mapping, tonemapping_operator_filmic,
    tonemapping_operator_gamma, tonemapping_operator_logarithmic,
    tonemapping_operator_logarithmic_mapping,
    tonemapping_operator_normalisation, tonemapping_operator_Reinhard2004,
    tonemapping_operator_Schlick1994, tonemapping_operator_simple,
    tonemapping_operator_Tumblin1999)

__author__ = 'Colour Developers'
__copyright__ = 'Copyright (C) 2015-2018 - Colour Developers'
__license__ = 'New BSD License - http://opensource.org/licenses/BSD-3-Clause'
__maintainer__ = 'Colour Developers'
__email__ = 'colour-science@googlegroups.com'
__status__ = 'Production'

__all__ = [
    'EXIF_EXECUTABLE', 'ExifTag', 'adjust_exposure', 'average_luminance',
    'copy_exif_tags', 'delete_exif_tags', 'exposure_value', 'filter_files',
    'Image', 'ImageStack', 'Metadata', 'parse_exif_array', 'parse_exif_data',
    'parse_exif_fraction', 'parse_exif_numeric', 'parse_exif_string',
    'path_exists', 'read_exif_tag', 'read_exif_tags', 'update_exif_tags',
    'vivification', 'vivified_to_dict', 'write_exif_tag'
]
__all__ += [
    'light_probe_sampling_variance_minimization_Viriyothai2009',
    'samples_Grossberg2003'
]
__all__ += [
    'normal_distribution_function', 'hat_function',
    'weighting_function_Debevec1997', 'image_stack_to_radiance_image'
]
__all__ += [
    'absolute_luminance_calibration_Lagarde2016',
    'camera_response_functions_Debevec1997', 'g_solve',
    'upper_hemisphere_illuminance_weights_Lagarde2016'
]
__all__ += [
    'camera_neutral_to_xy', 'camera_space_to_RGB', 'camera_space_to_sRGB',
    'camera_space_to_XYZ_matrix', 'xy_to_camera_neutral',
    'XYZ_to_camera_space_matrix'
]
__all__ += [
    'DNG_CONVERSION_ARGUMENTS', 'DNG_CONVERTER', 'DNG_EXIF_TAGS_BINDING',
    'RAW_CONVERSION_ARGUMENTS', 'RAW_CONVERTER', 'RAW_D_CONVERSION_ARGUMENTS',
    'convert_dng_files_to_intermediate_files',
    'convert_raw_files_to_dng_files', 'read_dng_files_exif_tags'
]
__all__ += ['highlights_recovery_blend', 'highlights_recovery_LCHab']
__all__ += [
    'tonemapping_operator_exponential',
    'tonemapping_operator_exponentiation_mapping',
    'tonemapping_operator_filmic', 'tonemapping_operator_gamma',
    'tonemapping_operator_logarithmic',
    'tonemapping_operator_logarithmic_mapping',
    'tonemapping_operator_normalisation', 'tonemapping_operator_Reinhard2004',
    'tonemapping_operator_Schlick1994', 'tonemapping_operator_simple',
    'tonemapping_operator_Tumblin1999'
]

RESOURCES_DIRECTORY = os.path.join(os.path.dirname(__file__), 'resources')
EXAMPLES_RESOURCES_DIRECTORY = os.path.join(RESOURCES_DIRECTORY,
                                            'colour-hdri-examples-dataset')
TESTS_RESOURCES_DIRECTORY = os.path.join(RESOURCES_DIRECTORY,
                                         'colour-hdri-tests-dataset')

__application_name__ = 'Colour - HDRI'

__major_version__ = '0'
__minor_version__ = '1'
__change_version__ = '4'
__version__ = '.'.join(
    (__major_version__,
     __minor_version__,
     __change_version__))  # yapf: disable

try:
    version = subprocess.check_output(
        ['git', 'describe'], cwd=os.path.dirname(__file__)).strip()
    version = version.decode('utf-8')
except subprocess.CalledProcessError:
    version = __version__

colour.utilities.ANCILLARY_COLOUR_SCIENCE_PACKAGES['colour-hdri'] = version
colour.utilities.ANCILLARY_RUNTIME_PACKAGES[
    'recordclass'] = recordclass.__version__

# TODO: Remove legacy printing support when deemed appropriate.
try:
    np.set_printoptions(legacy='1.13')
except TypeError:
    pass
<commit_msg>Broaden exception clause in "colour.utilities.describe_environment" definition.<commit_after># -*- coding: utf-8 -*-
"""
Colour - HDRI
=============

HDRI - Radiance image processing algorithms for *Python*.

Subpackages
-----------
-   calibration: Camera calibration computations.
-   examples: Examples for the sub-packages.
-   generation: HDRI / radiance image generation.
-   models: Colour models conversion.
-   plotting: Diagrams, figures, etc...
-   process: Image conversion helpers.
-   recovery: Clipped highlights recovery.
-   resources: Resources sub-modules.
-   sampling: Image sampling routines.
-   tonemapping: Tonemapping operators.
-   utilities: Various utilities and data structures.
"""

from __future__ import absolute_import

import numpy as np
import os
import recordclass
import subprocess

import colour

from .utilities import (
    EXIF_EXECUTABLE, ExifTag, adjust_exposure, average_luminance,
    copy_exif_tags, delete_exif_tags, exposure_value, filter_files, Image,
    ImageStack, Metadata, parse_exif_array, parse_exif_data,
    parse_exif_fraction, parse_exif_numeric, parse_exif_string, path_exists,
    read_exif_tag, read_exif_tags, update_exif_tags, vivification,
    vivified_to_dict, write_exif_tag)
from .sampling import (
    light_probe_sampling_variance_minimization_Viriyothai2009,
    samples_Grossberg2003)
from .generation import (normal_distribution_function, hat_function,
                         weighting_function_Debevec1997,
                         image_stack_to_radiance_image)
from .calibration import (absolute_luminance_calibration_Lagarde2016,
                          camera_response_functions_Debevec1997, g_solve,
                          upper_hemisphere_illuminance_weights_Lagarde2016)
from .models import (camera_neutral_to_xy, camera_space_to_RGB,
                     camera_space_to_sRGB, camera_space_to_XYZ_matrix,
                     xy_to_camera_neutral, XYZ_to_camera_space_matrix)
from .process import (DNG_CONVERSION_ARGUMENTS, DNG_CONVERTER,
                      DNG_EXIF_TAGS_BINDING, RAW_CONVERSION_ARGUMENTS,
                      RAW_CONVERTER, RAW_D_CONVERSION_ARGUMENTS,
                      convert_dng_files_to_intermediate_files,
                      convert_raw_files_to_dng_files, read_dng_files_exif_tags)
from .recovery import (highlights_recovery_blend, highlights_recovery_LCHab)
from .tonemapping import (
    tonemapping_operator_exponential,
    tonemapping_operator_exponentiation_mapping, tonemapping_operator_filmic,
    tonemapping_operator_gamma, tonemapping_operator_logarithmic,
    tonemapping_operator_logarithmic_mapping,
    tonemapping_operator_normalisation, tonemapping_operator_Reinhard2004,
    tonemapping_operator_Schlick1994, tonemapping_operator_simple,
    tonemapping_operator_Tumblin1999)

__author__ = 'Colour Developers'
__copyright__ = 'Copyright (C) 2015-2018 - Colour Developers'
__license__ = 'New BSD License - http://opensource.org/licenses/BSD-3-Clause'
__maintainer__ = 'Colour Developers'
__email__ = 'colour-science@googlegroups.com'
__status__ = 'Production'

__all__ = [
    'EXIF_EXECUTABLE', 'ExifTag', 'adjust_exposure', 'average_luminance',
    'copy_exif_tags', 'delete_exif_tags', 'exposure_value', 'filter_files',
    'Image', 'ImageStack', 'Metadata', 'parse_exif_array', 'parse_exif_data',
    'parse_exif_fraction', 'parse_exif_numeric', 'parse_exif_string',
    'path_exists', 'read_exif_tag', 'read_exif_tags', 'update_exif_tags',
    'vivification', 'vivified_to_dict', 'write_exif_tag'
]
__all__ += [
    'light_probe_sampling_variance_minimization_Viriyothai2009',
    'samples_Grossberg2003'
]
__all__ += [
    'normal_distribution_function', 'hat_function',
    'weighting_function_Debevec1997', 'image_stack_to_radiance_image'
]
__all__ += [
    'absolute_luminance_calibration_Lagarde2016',
    'camera_response_functions_Debevec1997', 'g_solve',
    'upper_hemisphere_illuminance_weights_Lagarde2016'
]
__all__ += [
    'camera_neutral_to_xy', 'camera_space_to_RGB', 'camera_space_to_sRGB',
    'camera_space_to_XYZ_matrix', 'xy_to_camera_neutral',
    'XYZ_to_camera_space_matrix'
]
__all__ += [
    'DNG_CONVERSION_ARGUMENTS', 'DNG_CONVERTER', 'DNG_EXIF_TAGS_BINDING',
    'RAW_CONVERSION_ARGUMENTS', 'RAW_CONVERTER', 'RAW_D_CONVERSION_ARGUMENTS',
    'convert_dng_files_to_intermediate_files',
    'convert_raw_files_to_dng_files', 'read_dng_files_exif_tags'
]
__all__ += ['highlights_recovery_blend', 'highlights_recovery_LCHab']
__all__ += [
    'tonemapping_operator_exponential',
    'tonemapping_operator_exponentiation_mapping',
    'tonemapping_operator_filmic', 'tonemapping_operator_gamma',
    'tonemapping_operator_logarithmic',
    'tonemapping_operator_logarithmic_mapping',
    'tonemapping_operator_normalisation', 'tonemapping_operator_Reinhard2004',
    'tonemapping_operator_Schlick1994', 'tonemapping_operator_simple',
    'tonemapping_operator_Tumblin1999'
]

RESOURCES_DIRECTORY = os.path.join(os.path.dirname(__file__), 'resources')
EXAMPLES_RESOURCES_DIRECTORY = os.path.join(RESOURCES_DIRECTORY,
                                            'colour-hdri-examples-dataset')
TESTS_RESOURCES_DIRECTORY = os.path.join(RESOURCES_DIRECTORY,
                                         'colour-hdri-tests-dataset')

__application_name__ = 'Colour - HDRI'

__major_version__ = '0'
__minor_version__ = '1'
__change_version__ = '4'
__version__ = '.'.join(
    (__major_version__,
     __minor_version__,
     __change_version__))  # yapf: disable

try:
    version = subprocess.check_output(
        ['git', 'describe'], cwd=os.path.dirname(__file__)).strip()
    version = version.decode('utf-8')
except Exception:
    version = __version__

colour.utilities.ANCILLARY_COLOUR_SCIENCE_PACKAGES['colour-hdri'] = version
colour.utilities.ANCILLARY_RUNTIME_PACKAGES[
    'recordclass'] = recordclass.__version__

# TODO: Remove legacy printing support when deemed appropriate.
try:
    np.set_printoptions(legacy='1.13')
except TypeError:
    pass
<|endoftext|>


<commit_before>
# by Albert Zeyer, www.az2000.de
# code under GPLv3+
# 2011-04-15

# This is a simple replacement for the standard Python exception handler (sys.excepthook).
# In addition to what the standard handler does, it also prints all referenced variables
# (no matter if local, global or builtin) of the code line of each stack frame.
# See below for some examples and some example output.

# https://github.com/albertz/py_better_exchook

import sys, os, os.path

def parse_py_statement(line):
	state = 0
	curtoken = ""
	spaces = " \t\n"
	ops = ".,;:+-*/%&=|(){}[]^<>"
	i = 0
	def _escape_char(c):
		if c == "n": return "\n"
		elif c == "t": return "\t"
		else: return c
	while i < len(line):
		c = line[i]
		i += 1
		if state == 0:
			if c in spaces: pass
			elif c in ops: yield ("op", c)
			elif c == "#": state = 6
			elif c == "\"": state = 1
			elif c == "'": state = 2
			else:
				curtoken = c
				state = 3
		elif state == 1: # string via "
			if c == "\\": state = 4
			elif c == "\"":
				yield ("str", curtoken)
				curtoken = ""
				state = 0
			else: curtoken += c
		elif state == 2: # string via '
			if c == "\\": state = 5
			elif c == "'":
				yield ("str", curtoken)
				curtoken = ""
				state = 0
			else: curtoken += c
		elif state == 3: # identifier
			if c in spaces + ops + "#\"'":
				yield ("id", curtoken)
				curtoken = ""
				state = 0
				i -= 1
			else: curtoken += c
		elif state == 4: # escape in "
			curtoken += _escape_char(c)
			state = 1
		elif state == 5: # escape in '
			curtoken += _escape_char(c)
			state = 2
		elif state == 6: # comment
			curtoken += c
	if state == 3: yield ("id", curtoken)
	elif state == 6: yield ("comment", curtoken)

pykeywords = set([
	"for","in","while","print","continue","break","del",
	"if","else","elif","yield","return","def","class",
	"raise","try","except","import","as","pass","lambda",
	"assert","and","or","not","is",
	])

def grep_full_py_identifiers(tokens):
	global pykeywords
	tokens = list(tokens)
	i = 0
	while i < len(tokens):
		tokentype, token = tokens[i]
		i += 1
		if tokentype != "id": continue
		while i+1 < len(tokens) and tokens[i] == ("op", ".") and tokens[i+1][0] == "id":
			token += "." + tokens[i+1][1]
			i += 2
		if token == "": continue
		if token in pykeywords: continue
		if token[0] in ".0123456789": continue
		yield token

def set_linecache(filename, source):
	import linecache
	linecache.cache[filename] = None, None, [line+'\n' for line in source.splitlines()], filename

def simple_debug_shell(globals, locals):
	try: import readline
	except: pass # ignore
	COMPILE_STRING_FN = "<simple_debug_shell input>"
	while True:
		try:
			s = raw_input("> ")
		except:
			print "breaked debug shell:", sys.exc_info()[0].__name__
			break
		try:
			c = compile(s, COMPILE_STRING_FN, "single")
		except Exception, e:
			print e.__class__.__name__, ":", str(e), "in", repr(s)
		else:
			set_linecache(COMPILE_STRING_FN, s)
			try:
				ret = eval(c, globals=globals, locals=locals)
			except:
				print "Error executing", repr(s)
				better_exchook(*sys.exc_info(), autodebugshell=False)
			else:
				try:
					if ret is not None: print ret
				except:
					print "Error printing return value of", repr(s)
					better_exchook(*sys.exc_info(), autodebugshell=False)

def debug_shell(user_ns, user_global_ns):
	ipshell = None
	try:
		from IPython.Shell import IPShellEmbed,IPShell
		ipshell = IPShell(argv=[], user_ns=user_ns, user_global_ns=user_global_ns)
	except: pass
	if ipshell:
		#ipshell()
		ipshell.mainloop()
	else:
		simple_debug_shell(user_global_ns, user_ns)

def output(s): print s

def output_limit():
	return 300

def pp_extra_info(obj, depthlimit = 3):
	s = []
	if hasattr(obj, "__len__"):
		try:
			if type(obj) in (str,unicode,list,tuple,dict) and len(obj) <= 5:
				pass # don't print len in this case
			else:
				s += ["len = " + str(obj.__len__())]
		except: pass
	if depthlimit > 0 and hasattr(obj, "__getitem__"):
		try:
			if type(obj) in (str,unicode):
				pass # doesn't make sense to get subitems here
			else:
				subobj = obj.__getitem__(0)
				extra_info = pp_extra_info(subobj, depthlimit - 1)
				if extra_info != "":
					s += ["_[0]: {" + extra_info + "}"]
		except: pass
	return ", ".join(s)

def pretty_print(obj):
	s = repr(obj)
	limit = output_limit()
	if len(s) > limit:
		s = s[:limit - 3] + "..."
	extra_info = pp_extra_info(obj)
	if extra_info != "": s += ", " + extra_info
	return s

def fallback_findfile(filename):
	mods = [ m for m in sys.modules.values() if m and hasattr(m, "__file__") and filename in m.__file__ ]
	if len(mods) == 0: return None
	altfn = mods[0].__file__
	if altfn[-4:-1] == ".py": altfn = altfn[:-1] # *.pyc or whatever
	return altfn

def better_exchook(etype, value, tb, debugshell=False, autodebugshell=True):
	output("EXCEPTION")
	output('Traceback (most recent call last):')
	topFrameLocals,topFrameGlobals = None,None
	try:
		import linecache
		limit = None
		if hasattr(sys, 'tracebacklimit'):
			limit = sys.tracebacklimit
		n = 0
		_tb = tb
		def _resolveIdentifier(namespace, id):
			obj = namespace[id[0]]
			for part in id[1:]:
				obj = getattr(obj, part)
			return obj
		def _trySet(old, prefix, func):
			if old is not None: return old
			try: return prefix + func()
			except KeyError: return old
			except Exception, e:
				return prefix + "!" + e.__class__.__name__ + ": " + str(e)
		while _tb is not None and (limit is None or n < limit):
			f = _tb.tb_frame
			topFrameLocals,topFrameGlobals = f.f_locals,f.f_globals
			lineno = _tb.tb_lineno
			co = f.f_code
			filename = co.co_filename
			name = co.co_name
			output('  File "%s", line %d, in %s' % (filename,lineno,name))
			if not os.path.isfile(filename):
				altfn = fallback_findfile(filename)
				if altfn:
					output("    -- couldn't find file, trying this instead: " + altfn)
					filename = altfn
			linecache.checkcache(filename)
			line = linecache.getline(filename, lineno, f.f_globals)
			if line:
				line = line.strip()
				output('    line: ' + line)
				output('    locals:')
				alreadyPrintedLocals = set()
				for tokenstr in grep_full_py_identifiers(parse_py_statement(line)):
					splittedtoken = tuple(tokenstr.split("."))
					for token in map(lambda i: splittedtoken[0:i], range(1, len(splittedtoken) + 1)):
						if token in alreadyPrintedLocals: continue
						tokenvalue = None
						tokenvalue = _trySet(tokenvalue, "<local> ", lambda: pretty_print(_resolveIdentifier(f.f_locals, token)))
						tokenvalue = _trySet(tokenvalue, "<global> ", lambda: pretty_print(_resolveIdentifier(f.f_globals, token)))
						tokenvalue = _trySet(tokenvalue, "<builtin> ", lambda: pretty_print(_resolveIdentifier(f.f_builtins, token)))
						tokenvalue = tokenvalue or "<not found>"
						output('      ' + ".".join(token) + " = " + tokenvalue)
						alreadyPrintedLocals.add(token)
				if len(alreadyPrintedLocals) == 0: output("       no locals")
			else:
				output('    -- code not available --')
			_tb = _tb.tb_next
			n += 1

	except Exception, e:
		output("ERROR: cannot get more detailed exception info because:")
		import traceback
		for l in traceback.format_exc().split("\n"): output("   " + l)
		output("simple traceback:")
		traceback.print_tb(tb)

	import types
	def _some_str(value):
		try: return str(value)
		except: return '<unprintable %s object>' % type(value).__name__
	def _format_final_exc_line(etype, value):
		valuestr = _some_str(value)
		if value is None or not valuestr:
			line = "%s" % etype
		else:
			line = "%s: %s" % (etype, valuestr)
		return line
	if (isinstance(etype, BaseException) or
		isinstance(etype, types.InstanceType) or
		etype is None or type(etype) is str):
		output(_format_final_exc_line(etype, value))
	else:
		output(_format_final_exc_line(etype.__name__, value))

	if autodebugshell:
		try: debugshell = int(os.environ["DEBUG"]) != 0
		except: pass
	if debugshell:
		output("---------- DEBUG SHELL -----------")
		debug_shell(user_ns=topFrameLocals, user_global_ns=topFrameGlobals)

def install():
	sys.excepthook = better_exchook

if __name__ == "__main__":
	# some examples
	# this code produces this output: https://gist.github.com/922622

	try:
		x = {1:2, "a":"b"}
		def f():
			y = "foo"
			x, 42, sys.stdin.__class__, sys.exc_info, y, z
		f()
	except:
		better_exchook(*sys.exc_info())

	try:
		f = lambda x: None
		f(x, y)
	except:
		better_exchook(*sys.exc_info())

	# use this to overwrite the global exception handler
	sys.excepthook = better_exchook
	# and fail
	finalfail(sys)
<commit_msg>better determination for py keywords<commit_after>
# by Albert Zeyer, www.az2000.de
# code under GPLv3+
# 2011-04-15

# This is a simple replacement for the standard Python exception handler (sys.excepthook).
# In addition to what the standard handler does, it also prints all referenced variables
# (no matter if local, global or builtin) of the code line of each stack frame.
# See below for some examples and some example output.

# https://github.com/albertz/py_better_exchook

import sys, os, os.path

def parse_py_statement(line):
	state = 0
	curtoken = ""
	spaces = " \t\n"
	ops = ".,;:+-*/%&=|(){}[]^<>"
	i = 0
	def _escape_char(c):
		if c == "n": return "\n"
		elif c == "t": return "\t"
		else: return c
	while i < len(line):
		c = line[i]
		i += 1
		if state == 0:
			if c in spaces: pass
			elif c in ops: yield ("op", c)
			elif c == "#": state = 6
			elif c == "\"": state = 1
			elif c == "'": state = 2
			else:
				curtoken = c
				state = 3
		elif state == 1: # string via "
			if c == "\\": state = 4
			elif c == "\"":
				yield ("str", curtoken)
				curtoken = ""
				state = 0
			else: curtoken += c
		elif state == 2: # string via '
			if c == "\\": state = 5
			elif c == "'":
				yield ("str", curtoken)
				curtoken = ""
				state = 0
			else: curtoken += c
		elif state == 3: # identifier
			if c in spaces + ops + "#\"'":
				yield ("id", curtoken)
				curtoken = ""
				state = 0
				i -= 1
			else: curtoken += c
		elif state == 4: # escape in "
			curtoken += _escape_char(c)
			state = 1
		elif state == 5: # escape in '
			curtoken += _escape_char(c)
			state = 2
		elif state == 6: # comment
			curtoken += c
	if state == 3: yield ("id", curtoken)
	elif state == 6: yield ("comment", curtoken)

import keyword
pykeywords = set(keyword.kwlist)

def grep_full_py_identifiers(tokens):
	global pykeywords
	tokens = list(tokens)
	i = 0
	while i < len(tokens):
		tokentype, token = tokens[i]
		i += 1
		if tokentype != "id": continue
		while i+1 < len(tokens) and tokens[i] == ("op", ".") and tokens[i+1][0] == "id":
			token += "." + tokens[i+1][1]
			i += 2
		if token == "": continue
		if token in pykeywords: continue
		if token[0] in ".0123456789": continue
		yield token

def set_linecache(filename, source):
	import linecache
	linecache.cache[filename] = None, None, [line+'\n' for line in source.splitlines()], filename

def simple_debug_shell(globals, locals):
	try: import readline
	except: pass # ignore
	COMPILE_STRING_FN = "<simple_debug_shell input>"
	while True:
		try:
			s = raw_input("> ")
		except:
			print "breaked debug shell:", sys.exc_info()[0].__name__
			break
		try:
			c = compile(s, COMPILE_STRING_FN, "single")
		except Exception, e:
			print e.__class__.__name__, ":", str(e), "in", repr(s)
		else:
			set_linecache(COMPILE_STRING_FN, s)
			try:
				ret = eval(c, globals=globals, locals=locals)
			except:
				print "Error executing", repr(s)
				better_exchook(*sys.exc_info(), autodebugshell=False)
			else:
				try:
					if ret is not None: print ret
				except:
					print "Error printing return value of", repr(s)
					better_exchook(*sys.exc_info(), autodebugshell=False)

def debug_shell(user_ns, user_global_ns):
	ipshell = None
	try:
		from IPython.Shell import IPShellEmbed,IPShell
		ipshell = IPShell(argv=[], user_ns=user_ns, user_global_ns=user_global_ns)
	except: pass
	if ipshell:
		#ipshell()
		ipshell.mainloop()
	else:
		simple_debug_shell(user_global_ns, user_ns)

def output(s): print s

def output_limit():
	return 300

def pp_extra_info(obj, depthlimit = 3):
	s = []
	if hasattr(obj, "__len__"):
		try:
			if type(obj) in (str,unicode,list,tuple,dict) and len(obj) <= 5:
				pass # don't print len in this case
			else:
				s += ["len = " + str(obj.__len__())]
		except: pass
	if depthlimit > 0 and hasattr(obj, "__getitem__"):
		try:
			if type(obj) in (str,unicode):
				pass # doesn't make sense to get subitems here
			else:
				subobj = obj.__getitem__(0)
				extra_info = pp_extra_info(subobj, depthlimit - 1)
				if extra_info != "":
					s += ["_[0]: {" + extra_info + "}"]
		except: pass
	return ", ".join(s)

def pretty_print(obj):
	s = repr(obj)
	limit = output_limit()
	if len(s) > limit:
		s = s[:limit - 3] + "..."
	extra_info = pp_extra_info(obj)
	if extra_info != "": s += ", " + extra_info
	return s

def fallback_findfile(filename):
	mods = [ m for m in sys.modules.values() if m and hasattr(m, "__file__") and filename in m.__file__ ]
	if len(mods) == 0: return None
	altfn = mods[0].__file__
	if altfn[-4:-1] == ".py": altfn = altfn[:-1] # *.pyc or whatever
	return altfn

def better_exchook(etype, value, tb, debugshell=False, autodebugshell=True):
	output("EXCEPTION")
	output('Traceback (most recent call last):')
	topFrameLocals,topFrameGlobals = None,None
	try:
		import linecache
		limit = None
		if hasattr(sys, 'tracebacklimit'):
			limit = sys.tracebacklimit
		n = 0
		_tb = tb
		def _resolveIdentifier(namespace, id):
			obj = namespace[id[0]]
			for part in id[1:]:
				obj = getattr(obj, part)
			return obj
		def _trySet(old, prefix, func):
			if old is not None: return old
			try: return prefix + func()
			except KeyError: return old
			except Exception, e:
				return prefix + "!" + e.__class__.__name__ + ": " + str(e)
		while _tb is not None and (limit is None or n < limit):
			f = _tb.tb_frame
			topFrameLocals,topFrameGlobals = f.f_locals,f.f_globals
			lineno = _tb.tb_lineno
			co = f.f_code
			filename = co.co_filename
			name = co.co_name
			output('  File "%s", line %d, in %s' % (filename,lineno,name))
			if not os.path.isfile(filename):
				altfn = fallback_findfile(filename)
				if altfn:
					output("    -- couldn't find file, trying this instead: " + altfn)
					filename = altfn
			linecache.checkcache(filename)
			line = linecache.getline(filename, lineno, f.f_globals)
			if line:
				line = line.strip()
				output('    line: ' + line)
				output('    locals:')
				alreadyPrintedLocals = set()
				for tokenstr in grep_full_py_identifiers(parse_py_statement(line)):
					splittedtoken = tuple(tokenstr.split("."))
					for token in map(lambda i: splittedtoken[0:i], range(1, len(splittedtoken) + 1)):
						if token in alreadyPrintedLocals: continue
						tokenvalue = None
						tokenvalue = _trySet(tokenvalue, "<local> ", lambda: pretty_print(_resolveIdentifier(f.f_locals, token)))
						tokenvalue = _trySet(tokenvalue, "<global> ", lambda: pretty_print(_resolveIdentifier(f.f_globals, token)))
						tokenvalue = _trySet(tokenvalue, "<builtin> ", lambda: pretty_print(_resolveIdentifier(f.f_builtins, token)))
						tokenvalue = tokenvalue or "<not found>"
						output('      ' + ".".join(token) + " = " + tokenvalue)
						alreadyPrintedLocals.add(token)
				if len(alreadyPrintedLocals) == 0: output("       no locals")
			else:
				output('    -- code not available --')
			_tb = _tb.tb_next
			n += 1

	except Exception, e:
		output("ERROR: cannot get more detailed exception info because:")
		import traceback
		for l in traceback.format_exc().split("\n"): output("   " + l)
		output("simple traceback:")
		traceback.print_tb(tb)

	import types
	def _some_str(value):
		try: return str(value)
		except: return '<unprintable %s object>' % type(value).__name__
	def _format_final_exc_line(etype, value):
		valuestr = _some_str(value)
		if value is None or not valuestr:
			line = "%s" % etype
		else:
			line = "%s: %s" % (etype, valuestr)
		return line
	if (isinstance(etype, BaseException) or
		isinstance(etype, types.InstanceType) or
		etype is None or type(etype) is str):
		output(_format_final_exc_line(etype, value))
	else:
		output(_format_final_exc_line(etype.__name__, value))

	if autodebugshell:
		try: debugshell = int(os.environ["DEBUG"]) != 0
		except: pass
	if debugshell:
		output("---------- DEBUG SHELL -----------")
		debug_shell(user_ns=topFrameLocals, user_global_ns=topFrameGlobals)

def install():
	sys.excepthook = better_exchook

if __name__ == "__main__":
	# some examples
	# this code produces this output: https://gist.github.com/922622

	try:
		x = {1:2, "a":"b"}
		def f():
			y = "foo"
			x, 42, sys.stdin.__class__, sys.exc_info, y, z
		f()
	except:
		better_exchook(*sys.exc_info())

	try:
		f = lambda x: None
		f(x, y)
	except:
		better_exchook(*sys.exc_info())

	# use this to overwrite the global exception handler
	sys.excepthook = better_exchook
	# and fail
	finalfail(sys)
<|endoftext|>