<commit_before>import concurrent.futures
from threading import Lock

import logging
log = logging.getLogger('nm_payment')

from nm_payment.base import PaymentSession, Payment
from nm_payment.exceptions import (
    SessionCompletedError, SessionCancelledError, CancelFailedError,
)

from .session import BBSSession


RUNNING = 'RUNNING'
CANCELLING = 'CANCELLING'
REVERSING = 'REVERSING'
FINISHED = 'FINISHED'
BROKEN = 'BROKEN'


class BBSPaymentSession(BBSSession, PaymentSession):
    def __init__(
            self, connection, amount, *, before_commit=None,
            on_print=None, on_display=None):
        super(BBSPaymentSession, self).__init__(connection)
        self._future = concurrent.futures.Future()
        self._lock = Lock()

        self._state = RUNNING

        self.amount = amount

        self._commit_callback = before_commit
        self._print_callback = on_print
        self._display_callback = on_display

        self._connection.request_transfer_amount(amount).result()

    def _start_reversal(self):
        try:
            self._state = REVERSING
            self._connection.request_reversal().result()
        except Exception as e:
            # XXX This is really really bad
            raise CancelFailedError() from e

    def _on_local_mode_running(self, result, **kwargs):
        if result == 'success':
            commit = True
            self._state == CANCELLING

            # TODO populate properly
            result_object = Payment(self.amount)
            if self._commit_callback is not None:
                # TODO can't decide on commit callback api
                try:
                    commit = self._commit_callback(result_object)
                except Exception:
                    commit = False

            if commit:
                self._state = FINISHED
                self._future.set_result(result_object)
            else:
                self._start_reversal()
        else:
            # TODO interpret errors from ITU
            self._state = FINISHED
            self._future.set_exception(SessionCancelledError("itu error"))

    def _on_local_mode_cancelling(self, result, **kwargs):
        if result == 'success':
            self._start_reversal()
        else:
            self._state = FINISHED
            self._future.set_exception(SessionCancelledError())

    def _on_local_mode_reversing(self, result, **kwargs):
        if result == 'success':
            self._state = FINISHED
            self._future.set_exception(SessionCancelledError())
        else:<commit_msg>log commit callback exceptions<commit_after>import concurrent.futures
from threading import Lock

import logging
log = logging.getLogger('nm_payment')

from nm_payment.base import PaymentSession, Payment
from nm_payment.exceptions import (
    SessionCompletedError, SessionCancelledError, CancelFailedError,
)

from .session import BBSSession


RUNNING = 'RUNNING'
CANCELLING = 'CANCELLING'
REVERSING = 'REVERSING'
FINISHED = 'FINISHED'
BROKEN = 'BROKEN'


class BBSPaymentSession(BBSSession, PaymentSession):
    def __init__(
            self, connection, amount, *, before_commit=None,
            on_print=None, on_display=None):
        super(BBSPaymentSession, self).__init__(connection)
        self._future = concurrent.futures.Future()
        self._lock = Lock()

        self._state = RUNNING

        self.amount = amount

        self._commit_callback = before_commit
        self._print_callback = on_print
        self._display_callback = on_display

        self._connection.request_transfer_amount(amount).result()

    def _start_reversal(self):
        try:
            self._state = REVERSING
            self._connection.request_reversal().result()
        except Exception as e:
            # XXX This is really really bad
            raise CancelFailedError() from e

    def _on_local_mode_running(self, result, **kwargs):
        if result == 'success':
            commit = True
            self._state == CANCELLING

            # TODO populate properly
            result_object = Payment(self.amount)
            if self._commit_callback is not None:
                # TODO can't decide on commit callback api
                try:
                    commit = self._commit_callback(result_object)
                except Exception:
                    log.exception("error in commit callback")
                    commit = False

            if commit:
                self._state = FINISHED
                self._future.set_result(result_object)
            else:
                self._start_reversal()
        else:
            # TODO interpret errors from ITU
            self._state = FINISHED
            self._future.set_exception(SessionCancelledError("itu error"))

    def _on_local_mode_cancelling(self, result, **kwargs):
        if result == 'success':
            self._start_reversal()
        else:
            self._state = FINISHED
            self._future.set_exception(SessionCancelledError())

    def _on_local_mode_reversing(self, result, **kwargs):
        if result == 'success':
            self._state = FINISHED
            self._future.set_exception(SessionCancelledError())
        else:
{'fraction_non_alphanumeric': 0.0781040107464978, 'fraction_numerical': 0.0, 'mean_word_length': 2.2192711550339714, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1446852', 'n_tokens_mistral': 1432, 'n_tokens_neox': 1356, 'n_words': 322}