コード例 #1
0
    def _get_renderer_factory(self, media_type, renderer):
        """Given two bytestrings, return a renderer factory or None.
        """
        typecheck(media_type, str, renderer, str)
        if renderer_re.match(renderer) is None:
            possible = ', '.join(sorted(
                self.website.renderer_factories.keys()))
            msg = ("Malformed renderer %s. It must match %s. Possible "
                   "renderers (might need third-party libs): %s.")
            raise SyntaxError(msg % (renderer, renderer_re.pattern, possible))
        renderer = renderer[2:]  # strip off the hashbang
        renderer = renderer.decode('US-ASCII')

        factories = self.website.renderer_factories
        make_renderer = factories.get(renderer, None)
        if isinstance(make_renderer, ImportError):
            raise make_renderer
        elif make_renderer is None:
            possible = []
            want_legend = False
            for k, v in sorted(factories.iteritems()):
                if isinstance(v, ImportError):
                    k = '*' + k
                    want_legend = True
                possible.append(k)
            possible = ', '.join(possible)
            if want_legend:
                legend = " (starred are missing third-party libraries)"
            else:
                legend = ''
            raise ValueError("Unknown renderer for %s: %s. Possible "
                             "renderers%s: %s." %
                             (media_type, renderer, legend, possible))
        return make_renderer
コード例 #2
0
def authorize(participant_id, pmt):
    """Given two unicodes, return a dict.

    This function attempts to authorize the credit card details referenced by
    pmt. If the attempt succeeds we cancel the transaction. If it fails we log
    the failure. Even for failure we keep the payment_method_token, we don't
    reset it to None/NULL. It's useful for loading the previous (bad) credit
    card info from Samurai in order to prepopulate the form.

    """
    typecheck(pmt, unicode, participant_id, unicode)
    transaction = Processor.authorize(pmt, '1.00', custom=participant_id)
    if transaction.errors:
        last_bill_result = json.dumps(transaction.errors)
        out = dict(transaction.errors)
    else:
        transaction.reverse()
        last_bill_result = ''
        out = {}

    STANDING = """\

    UPDATE participants
       SET payment_method_token=%s
         , last_bill_result=%s 
     WHERE id=%s

    """
    db.execute(STANDING, (pmt, last_bill_result, participant_id))
    return out
コード例 #3
0
ファイル: payday.py プロジェクト: paparent/www.gittip.com
        def genparticipants(for_payday):
            """Closure generator to yield participants with tips and total.

            We re-fetch participants each time, because the second time through
            we want to use the total obligations they have for next week, and
            if we pass a non-False for_payday to get_tips_and_total then we
            only get unfulfilled tips from prior to that timestamp, which is
            none of them by definition.

            If someone changes tips after payout starts, and we crash during
            payout, then their new tips_and_total will be used on the re-run.
            That's okay.

            Note that we take ts_start from the outer scope when we pass it to
            get_participants, but we pass in for_payday, because we might want
            it to be False (per the definition of git_tips_and_total).

            """
            for participant in self.get_participants(ts_start):
                tips, total = get_tips_and_total( participant['id']
                                                , for_payday=for_payday
                                                , db=self.db
                                                 )
                typecheck(total, Decimal)
                yield(participant, tips, total)
コード例 #4
0
def upcharge(amount):
    """Given an amount, return a higher amount and the difference.
    """
    typecheck(amount, Decimal)
    charge_amount = (amount + FEE_CHARGE[0]) / (1 - FEE_CHARGE[1])
    charge_amount = charge_amount.quantize(FEE_CHARGE[0], rounding=ROUND_UP)
    return charge_amount, charge_amount - amount
コード例 #5
0
ファイル: billing.py プロジェクト: mwhite/www.gittip.com
def transfer(tipper, tippee, amount):
    """Given two unicodes and a Decimal, return a boolean indicating success.

    If the tipper doesn't have enough in their Gittip account then we return
    False. Otherwise we decrement tipper's balance and increment tippee's
    *pending* balance by amount.

    """
    typecheck(tipper, unicode, tippee, unicode, amount, decimal.Decimal)
    with db.get_connection() as conn:
        cursor = conn.cursor()

        try:
            debit_participant(cursor, tipper, amount)
        except ValueError:
            return False

        credit_participant(cursor, tippee, amount)
        record_transfer(cursor, tipper, tippee, amount)
        increment_payday(cursor, amount)

        # Success.
        # ========

        conn.commit()
        return True
コード例 #6
0
ファイル: billing.py プロジェクト: bglusman/www.gittip.com
def authorize(participant_id, pmt):
    """Given two unicodes, return a dict.

    This function attempts to authorize the credit card details referenced by
    pmt. If the attempt succeeds we cancel the transaction. If it fails we log
    the failure. Even for failure we keep the payment_method_token, we don't
    reset it to None/NULL. It's useful for loading the previous (bad) credit
    card info from Samurai in order to prepopulate the form.

    """
    typecheck(pmt, unicode, participant_id, unicode)
    transaction = Processor.authorize(pmt, '1.00', custom=participant_id)
    if transaction.errors:
        last_bill_result = json.dumps(transaction.errors)
        out = dict(transaction.errors)
    else:
        transaction.reverse()
        last_bill_result = ''
        out = {}
        
    STANDING = """\

    UPDATE participants
       SET payment_method_token=%s
         , last_bill_result=%s 
     WHERE id=%s

    """
    db.execute(STANDING, (pmt, last_bill_result, participant_id))
    return out
コード例 #7
0
ファイル: exchanges.py プロジェクト: augmen/gratipay.com
def capture_card_hold(db, participant, amount, hold):
    """Capture the previously created hold on the participant's credit card.
    """
    typecheck( hold, balanced.CardHold
             , amount, Decimal
              )

    username = participant.username
    assert participant.id == int(hold.meta['participant_id'])

    route = ExchangeRoute.from_address(participant, 'balanced-cc', hold.card_href)
    assert isinstance(route, ExchangeRoute)

    cents, amount_str, charge_amount, fee = _prep_hit(amount)
    amount = charge_amount - fee  # account for possible rounding
    e_id = record_exchange(db, route, amount, fee, participant, 'pre')

    meta = dict(participant_id=participant.id, exchange_id=e_id)
    try:
        hold.capture(amount=cents, description=username, meta=meta)
        record_exchange_result(db, e_id, 'succeeded', None, participant)
    except Exception as e:
        error = repr_exception(e)
        record_exchange_result(db, e_id, 'failed', error, participant)
        raise

    hold.meta['state'] = 'captured'
    hold.save()

    log("Captured " + amount_str + " on Balanced for " + username)
コード例 #8
0
def capture_card_hold(db, participant, amount, hold):
    """Capture the previously created hold on the participant's credit card.
    """
    typecheck( hold, braintree.Transaction
             , amount, Decimal
              )

    username = participant.username
    assert participant.id == int(hold.custom_fields['participant_id'])

    route = ExchangeRoute.from_address(participant, 'braintree-cc', hold.credit_card['token'])
    assert isinstance(route, ExchangeRoute)

    cents, amount_str, charge_amount, fee = _prep_hit(amount)
    amount = charge_amount - fee  # account for possible rounding
    e_id = record_exchange(db, route, amount, fee, participant, 'pre')

    # TODO: Find a way to link transactions and corresponding exchanges
    # meta = dict(participant_id=participant.id, exchange_id=e_id)

    error = ''
    try:
        result = braintree.Transaction.submit_for_settlement(hold.id, str(cents/100.00))
        assert result.is_success
        if result.transaction.status != 'submitted_for_settlement':
            error = result.transaction.status
    except Exception as e:
        error = repr_exception(e)

    if error == '':
        record_exchange_result(db, e_id, 'succeeded', None, participant)
        log("Captured " + amount_str + " on Braintree for " + username)
    else:
        record_exchange_result(db, e_id, 'failed', error, participant)
        raise Exception(error)
コード例 #9
0
ファイル: twitter.py プロジェクト: DylanLacey/www.gittip.com
def get_user_info(screen_name):
    """Given a unicode, return a dict.
    """
    typecheck(screen_name, unicode)
    try:
        rec = gittip.db.one( "SELECT user_info FROM elsewhere "
                             "WHERE platform='twitter' "
                             "AND user_info->'screen_name' = %s"
                           , (screen_name,)
                            )
    except TooFew:
        rec = None

    if rec is not None:
        user_info = rec['user_info']
    else:
        # Updated using Twython as a point of reference:
        # https://github.com/ryanmcgrath/twython/blob/master/twython/twython.py#L76
        oauth = OAuth1(
            # we do not have access to the website obj,
            # so let's grab the details from the env
            environ['TWITTER_CONSUMER_KEY'],
            environ['TWITTER_CONSUMER_SECRET'],
            environ['TWITTER_ACCESS_TOKEN'],
            environ['TWITTER_ACCESS_TOKEN_SECRET'],
        )

        url = "https://api.twitter.com/1.1/users/show.json?screen_name=%s"
        user_info = requests.get(url % screen_name, auth=oauth)

        # Keep an eye on our Twitter usage.
        # =================================

        rate_limit = user_info.headers['X-Rate-Limit-Limit']
        rate_limit_remaining = user_info.headers['X-Rate-Limit-Remaining']
        rate_limit_reset = user_info.headers['X-Rate-Limit-Reset']

        try:
            rate_limit = int(rate_limit)
            rate_limit_remaining = int(rate_limit_remaining)
            rate_limit_reset = int(rate_limit_reset)
        except (TypeError, ValueError):
            log( "Got weird rate headers from Twitter: %s %s %s"
               % (rate_limit, rate_limit_remaining, rate_limit_reset)
                )
        else:
            reset = datetime.datetime.fromtimestamp(rate_limit_reset, tz=utc)
            reset = to_age(reset)
            log( "Twitter API calls used: %d / %d. Resets %s."
               % (rate_limit - rate_limit_remaining, rate_limit, reset)
                )


        if user_info.status_code == 200:
            user_info = json.loads(user_info.text)
        else:
            log("Twitter lookup failed with %d." % user_info.status_code)
            raise Response(404)

    return user_info
コード例 #10
0
    def charge(self, participant_id, balanced_account_uri, stripe_customer_id,
               amount):
        """Given three unicodes and a Decimal, return a boolean.

        This is the only place where we actually charge credit cards. Amount
        should be the nominal amount. We'll compute Gittip's fee below this
        function and add it to amount to end up with charge_amount.

        """
        typecheck(participant_id, unicode, balanced_account_uri,
                  (unicode, None), amount, Decimal)

        if balanced_account_uri is None and stripe_customer_id is None:
            self.mark_missing_funding()
            return False

        if balanced_account_uri is not None:
            things = self.charge_on_balanced(participant_id,
                                             balanced_account_uri, amount)
            charge_amount, fee, error = things
        else:
            assert stripe_customer_id is not None
            things = self.charge_on_stripe(participant_id, stripe_customer_id,
                                           amount)
            charge_amount, fee, error = things

        amount = charge_amount - fee  # account for possible rounding under
        # charge_on_*

        self.record_charge(amount, charge_amount, fee, error, participant_id)

        return not bool(error)  # True indicates success
コード例 #11
0
ファイル: __init__.py プロジェクト: worthyapp/www.gittip.com
def get_balanced_account(username, balanced_account_uri):
    """Find or create a balanced.Account.
    """
    typecheck(username, unicode, balanced_account_uri, (unicode, None))

    # XXX Balanced requires an email address
    # https://github.com/balanced/balanced-api/issues/20
    # quote to work around https://github.com/gittip/www.gittip.com/issues/781
    email_address = '{}@gittip.com'.format(quote(username))

    if balanced_account_uri is None:
        try:
            account = \
               balanced.Account.query.filter(email_address=email_address).one()
        except balanced.exc.NoResultFound:
            account = balanced.Account(email_address=email_address).save()
        BALANCED_ACCOUNT = """\

                UPDATE participants
                   SET balanced_account_uri=%s
                 WHERE username=%s

        """
        gittip.db.run(BALANCED_ACCOUNT, (account.uri, username))
        account.meta['username'] = username
        account.save()  # HTTP call under here
    else:
        account = balanced.Account.find(balanced_account_uri)
    return account
コード例 #12
0
ファイル: exchanges.py プロジェクト: ledreamer/gratipay.com
def capture_card_hold(db, participant, amount, hold):
    """Capture the previously created hold on the participant's credit card.
    """
    typecheck(hold, balanced.CardHold, amount, Decimal)

    username = participant.username
    assert participant.id == int(hold.meta['participant_id'])

    cents, amount_str, charge_amount, fee = _prep_hit(amount)
    amount = charge_amount - fee  # account for possible rounding
    e_id = record_exchange(db, 'bill', amount, fee, participant, 'pre')

    meta = dict(participant_id=participant.id, exchange_id=e_id)
    try:
        hold.capture(amount=cents, description=username, meta=meta)
        record_exchange_result(db, e_id, 'succeeded', None, participant)
    except Exception as e:
        error = repr_exception(e)
        record_exchange_result(db, e_id, 'failed', error, participant)
        raise

    hold.meta['state'] = 'captured'
    hold.save()

    log("Captured " + amount_str + " on Balanced for " + username)
コード例 #13
0
ファイル: github.py プロジェクト: Web5design/www.gittip.com
def get_user_info(login):
    """Get the given user's information from the DB or failing that, github.

    :param login:
        A unicode string representing a username in github.

    :returns:
        A dictionary containing github specific information for the user.
    """
    typecheck(login, unicode)
    rec = gittip.db.fetchone( "SELECT user_info FROM elsewhere "
                              "WHERE platform='github' "
                              "AND user_info->'login' = %s"
                            , (login,)
                             )
    if rec is not None:
        user_info = rec['user_info']
    else:
        url = "https://api.github.com/users/%s"
        user_info = requests.get(url % login, params={
            'client_id': os.environ.get('GITHUB_CLIENT_ID'),
            'client_secret': os.environ.get('GITHUB_CLIENT_SECRET')
        })
        status = user_info.status_code
        content = user_info.text

        # Calculate how much of our ratelimit we have consumed
        remaining = int(user_info.headers['x-ratelimit-remaining'])
        limit = int(user_info.headers['x-ratelimit-limit'])
        # thanks to from __future__ import division this is a float
        percent_remaining = remaining/limit

        log_msg = ''
        log_lvl = None
        # We want anything 50% or over
        if 0.5 <= percent_remaining:
            log_msg = ("{0}% of GitHub's ratelimit has been consumed. {1}"
                       " requests remaining.").format(percent_remaining * 100,
                                                      remaining)
        if 0.5 <= percent_remaining < 0.8:
            log_lvl = logging.WARNING
        elif 0.8 <= percent_remaining < 0.95:
            log_lvl = logging.ERROR
        elif 0.95 <= percent_remaining:
            log_lvl = logging.CRITICAL

        if log_msg and log_lvl:
            log(log_msg, log_lvl)

        if status == 200:
            user_info = json.loads(content)
        elif status == 404:
            raise Response(404,
                           "GitHub identity '{0}' not found.".format(login))
        else:
            log("Github api responded with {0}: {1}".format(status, content),
                level=logging.WARNING)
            raise Response(502, "GitHub lookup failed with %d." % status)

    return user_info
コード例 #14
0
def get_balanced_account(participant_id, balanced_account_uri):
    """Find or create a balanced.Account.
    """
    typecheck(participant_id, unicode, balanced_account_uri, (unicode, None))

    # XXX Balanced requires an email address
    # https://github.com/balanced/balanced-api/issues/20

    email_address = '{}@gittip.com'.format(participant_id)

    if balanced_account_uri is None:
        try:
            account = \
               balanced.Account.query.filter(email_address=email_address).one()
        except balanced.exc.NoResultFound:
            account = balanced.Account(email_address=email_address).save()
        BALANCED_ACCOUNT = """\

                UPDATE participants
                   SET balanced_account_uri=%s
                 WHERE id=%s

        """
        gittip.db.execute(BALANCED_ACCOUNT, (account.uri, participant_id))
        account.meta['participant_id'] = participant_id
        account.save()  # HTTP call under here
    else:
        account = balanced.Account.find(balanced_account_uri)
    return account
コード例 #15
0
ファイル: payday.py プロジェクト: reedlaw/www.gittip.com
def upcharge(amount):
    """Given an amount, return a higher amount and the difference.
    """
    typecheck(amount, Decimal)
    charge_amount = (amount + FEE_CHARGE[0]) / (1 - FEE_CHARGE[1])
    charge_amount = charge_amount.quantize(FEE_CHARGE[0], rounding=ROUND_UP)
    return charge_amount, charge_amount - amount
コード例 #16
0
ファイル: __init__.py プロジェクト: rauhryan/www.gittip.com
    def __init__(self, db, user_id, user_info=None, existing_record=None):
        """Either:
        - Takes a user_id and user_info, and updates the database.

        Or:
        - Takes a user_id and existing_record, and constructs a "model" object out of the record
        """
        typecheck(user_id, (int, unicode, long), user_info, (None, dict))
        self.user_id = unicode(user_id)
        self.db = db

        if user_info is not None:
            a, b, c, d = self.upsert(user_info)

            self.participant = a
            self.is_claimed = b
            self.is_locked = c
            self.balance = d

            self.user_info = user_info

        # hack to make this into a weird pseudo-model that can share convenience methods
        elif existing_record is not None:
            self.participant = existing_record.participant
            self.is_claimed, self.is_locked, self.balance = self.get_misc_info(self.participant)
            self.user_info = existing_record.user_info
            self.record = existing_record
コード例 #17
0
ファイル: __init__.py プロジェクト: smitzter/gratipay.com
def wrap(u):
    """Given a unicode, return a unicode.
    """
    typecheck(u, unicode)
    linkified = linkify(u)  # Do this first, because it calls xthml_escape.
    out = linkified.replace(u'\r\n', u'<br />\r\n').replace(u'\n', u'<br />\n')
    return out if out else '...'
コード例 #18
0
    def __init__(self, d):
        """Takes headers as a dict or str.
        """
        typecheck(d, (dict, str))
        if isinstance(d, str):
            from aspen.exceptions import MalformedHeader

            def genheaders():
                for line in d.splitlines():
                    if b':' not in line:
                        # no colon separator in header
                        raise MalformedHeader(line)
                    k, v = line.split(b':', 1)
                    if k != k.strip():
                        # disallowed leading or trailing whitspace
                        # (per http://tools.ietf.org/html/rfc7230#section-3.2.4)
                        raise MalformedHeader(line)
                    yield k, v.strip()
        else:
            genheaders = d.iteritems
        CaseInsensitiveMapping.__init__(self, genheaders)

        # Cookie
        # ======

        self.cookie = SimpleCookie()
        try:
            self.cookie.load(self.get('Cookie', b''))
        except CookieError:
            pass  # XXX really?
コード例 #19
0
    def get_img_src(self, size=128):
        """Return a value for <img src="..." />.

        Until we have our own profile pics, delegate. XXX Is this an attack
        vector? Can someone inject this value? Don't think so, but if you make
        it happen, let me know, eh? Thanks. :)

            https://www.gittip.com/security.txt

        """
        typecheck(size, int)

        src = '/assets/%s/avatar-default.gif' % os.environ['__VERSION__']

        github, twitter, bitbucket, bountysource = self.get_accounts_elsewhere()
        if github is not None:
            # GitHub -> Gravatar: http://en.gravatar.com/site/implement/images/
            if 'gravatar_id' in github.user_info:
                gravatar_hash = github.user_info['gravatar_id']
                src = "https://www.gravatar.com/avatar/%s.jpg?s=%s"
                src %= (gravatar_hash, size)

        elif twitter is not None:
            # https://dev.twitter.com/docs/api/1.1/get/users/show
            if 'profile_image_url_https' in twitter.user_info:
                src = twitter.user_info['profile_image_url_https']

                # For Twitter, we don't have good control over size. The
                # biggest option is 73px(?!), but that's too small. Let's go
                # with the original: even though it may be huge, that's
                # preferrable to guaranteed blurriness. :-/

                src = src.replace('_normal.', '.')

        return src
コード例 #20
0
ファイル: payday.py プロジェクト: Siecje/www.gittip.com
    def transfer(self, tipper, tippee, amount, pachinko=False):
        """Given two unicodes, a Decimal, and a boolean, return a boolean.

        If the tipper doesn't have enough in their Gittip account then we
        return False. Otherwise we decrement tipper's balance and increment
        tippee's *pending* balance by amount.

        """
        typecheck( tipper, unicode
                 , tippee, unicode
                 , amount, Decimal
                 , pachinko, bool
                  )
        with self.db.get_cursor() as cursor:

            try:
                self.debit_participant(cursor, tipper, amount)
            except NegativeBalance:
                return False

            self.credit_participant(cursor, tippee, amount)
            context = 'take' if pachinko else 'tip'
            self.record_transfer(cursor, tipper, tippee, amount, context)

            return True
コード例 #21
0
def capture_card_hold(db, participant, amount, hold):
    """Capture the previously created hold on the participant's credit card.
    """
    typecheck( hold, braintree.Transaction
             , amount, Decimal
              )

    username = participant.username
    assert participant.id == int(hold.custom_fields['participant_id'])

    route = ExchangeRoute.from_address(participant, 'braintree-cc', hold.credit_card['token'])
    assert isinstance(route, ExchangeRoute)

    cents, amount_str, charge_amount, fee = _prep_hit(amount)
    amount = charge_amount - fee  # account for possible rounding
    e_id = record_exchange(db, route, amount, fee, participant, 'pre')

    # TODO: Find a way to link transactions and corresponding exchanges
    # meta = dict(participant_id=participant.id, exchange_id=e_id)

    error = ''
    try:
        result = braintree.Transaction.submit_for_settlement(hold.id, str(cents/100.00))
        assert result.is_success
        if result.transaction.status != 'submitted_for_settlement':
            error = result.transaction.status
    except Exception as e:
        error = repr_exception(e)

    if error == '':
        record_exchange_result(db, e_id, 'succeeded', None, participant)
        log("Captured " + amount_str + " on Braintree for " + username)
    else:
        record_exchange_result(db, e_id, 'failed', error, participant)
        raise Exception(error)
コード例 #22
0
ファイル: __init__.py プロジェクト: bmispelon/www.gittip.com
def get_balanced_account(username, balanced_account_uri):
    """Find or create a balanced.Account.
    """
    typecheck( username, unicode
             , balanced_account_uri, (unicode, None)
              )

    # XXX Balanced requires an email address
    # https://github.com/balanced/balanced-api/issues/20
    # quote to work around https://github.com/gittip/www.gittip.com/issues/781
    email_address = '{}@gittip.com'.format(quote(username))


    if balanced_account_uri is None:
        try:
            account = \
               balanced.Account.query.filter(email_address=email_address).one()
        except balanced.exc.NoResultFound:
            account = balanced.Account(email_address=email_address).save()
        BALANCED_ACCOUNT = """\

                UPDATE participants
                   SET balanced_account_uri=%s
                 WHERE username=%s

        """
        gittip.db.run(BALANCED_ACCOUNT, (account.uri, username))
        account.meta['username'] = username
        account.save()  # HTTP call under here
    else:
        account = balanced.Account.find(balanced_account_uri)
    return account
コード例 #23
0
def get_user_info(db, username):
    """Get the given user's information from the DB or failing that, bitbucket.

    :param username:
        A unicode string representing a username in bitbucket.

    :returns:
        A dictionary containing bitbucket specific information for the user.
    """
    typecheck(username, (unicode, PathPart))
    rec = db.one(
        """
        SELECT user_info FROM elsewhere
        WHERE platform='bitbucket'
        AND user_info->'username' = %s
    """,
        (username,),
    )
    if rec is not None:
        user_info = rec
    else:
        url = "%s/users/%s?pagelen=100"
        user_info = requests.get(url % (BASE_API_URL, username))
        status = user_info.status_code
        content = user_info.content
        if status == 200:
            user_info = json.loads(content)["user"]
        elif status == 404:
            raise Response(404, "Bitbucket identity '{0}' not found.".format(username))
        else:
            log("Bitbucket api responded with {0}: {1}".format(status, content), level=logging.WARNING)
            raise Response(502, "Bitbucket lookup failed with %d." % status)

    return user_info
コード例 #24
0
ファイル: __init__.py プロジェクト: Irkinosor/gratipay.com
def clear(db, thing, username, balanced_customer_href):
    typecheck( thing, unicode
             , username, unicode
             , balanced_customer_href, (unicode, str)
              )
    invalidate_on_balanced(thing, balanced_customer_href)
    store_result(db, thing, username, None)
コード例 #25
0
ファイル: __init__.py プロジェクト: ledreamer/gratipay.com
def associate(db, thing, participant, balanced_account, balanced_thing_uri):
    """Given four unicodes, return a unicode.

    This function attempts to associate the credit card or bank account details
    referenced by balanced_thing_uri with a Balanced Account. If it fails we
    log and return a unicode describing the failure. Even for failure we keep
    balanced_customer_href; we don't reset it to None/NULL. It's useful for
    loading the previous (bad) info from Balanced in order to prepopulate the
    form.

    """
    typecheck(participant, Participant, balanced_account, balanced.Customer,
              balanced_thing_uri, unicode, thing, unicode)

    invalidate_on_balanced(thing, balanced_account)
    try:
        if thing == "credit card":
            obj = balanced.Card.fetch(balanced_thing_uri)
        else:
            assert thing == "bank account", thing  # sanity check
            obj = balanced.BankAccount.fetch(balanced_thing_uri)
        obj.associate_to_customer(balanced_account)
    except balanced.exc.HTTPError as err:
        error = err.message.message.decode('UTF-8')  # XXX UTF-8?
    else:
        error = ''
    typecheck(error, unicode)

    store_result(db, thing, participant, error)
    return error
コード例 #26
0
ファイル: payday.py プロジェクト: booo/www.gittip.com
    def hit_balanced(self, participant_id, balanced_account_uri, amount):
        """We have a purported balanced_account_uri. Try to use it.
        """
        typecheck( participant_id, unicode
                 , balanced_account_uri, unicode
                 , amount, Decimal
                  )

        try_charge_amount = (amount + FEE[0]) * FEE[1]
        try_charge_amount = try_charge_amount.quantize( FEE[0]
                                                      , rounding=ROUND_UP
                                                       )
        charge_amount = try_charge_amount
        also_log = ''
        if charge_amount < MINIMUM:
            charge_amount = MINIMUM  # per Balanced
            also_log = ', rounded up to $%s' % charge_amount

        fee = try_charge_amount - amount
        cents = int(charge_amount * 100)

        msg = "Charging %s %d cents ($%s + $%s fee = $%s%s) ... "
        msg %= participant_id, cents, amount, fee, try_charge_amount, also_log

        try:
            customer = balanced.Account.find(balanced_account_uri)
            customer.debit(cents, description=participant_id)
            log(msg + "succeeded.")
        except balanced.exc.HTTPError as err:
            log(msg + "failed: %s" % err.message)
            return charge_amount, fee, err.message

        return charge_amount, fee, None
コード例 #27
0
def clear(thing, participant_id, balanced_account_uri):
    typecheck( thing, unicode
             , participant_id, unicode
             , balanced_account_uri, unicode
              )
    assert thing in ("credit card", "bank account"), thing


    # XXX Things in balanced cannot be deleted at the moment.
    # =======================================================
    # Instead we mark all valid cards as invalid which will restrict against
    # anyone being able to issue charges against them in the future.
    #
    # See: https://github.com/balanced/balanced-api/issues/22

    account = balanced.Account.find(balanced_account_uri)
    things = account.cards if thing == "credit card" else account.bank_accounts

    for _thing in things:
        if _thing.is_valid:
            _thing.is_valid = False
            _thing.save()

    CLEAR = """\

        UPDATE participants
           SET last_%s_result=NULL
         WHERE id=%%s

    """ % ("bill" if thing == "credit card" else "ach")
    db.execute(CLEAR, (participant_id,))
コード例 #28
0
ファイル: payday.py プロジェクト: DylanLacey/www.gittip.com
    def transfer(self, tipper, tippee, amount, pachinko=False):
        """Given two unicodes, a Decimal, and a boolean, return a boolean.

        If the tipper doesn't have enough in their Gittip account then we
        return False. Otherwise we decrement tipper's balance and increment
        tippee's *pending* balance by amount.

        """
        typecheck( tipper, unicode
                 , tippee, unicode
                 , amount, Decimal
                 , pachinko, bool
                  )
        with self.db.get_connection() as conn:
            cursor = conn.cursor()

            try:
                self.debit_participant(cursor, tipper, amount)
            except IntegrityError:
                return False

            self.credit_participant(cursor, tippee, amount)
            self.record_transfer(cursor, tipper, tippee, amount)
            if pachinko:
                self.mark_pachinko(cursor, amount)
            else:
                self.mark_transfer(cursor, amount)

            conn.commit()
            return True
コード例 #29
0
def get_user_info(db, username, osm_api_url):
    """Get the given user's information from the DB or failing that, openstreetmap.

    :param username:
        A unicode string representing a username in OpenStreetMap.

    :param osm_api_url:
	URL of OpenStreetMap API.

    :returns:
        A dictionary containing OpenStreetMap specific information for the user.
    """
    typecheck(username, (unicode, PathPart))
    rec = db.one("""
        SELECT user_info FROM elsewhere
        WHERE platform='openstreetmap'
        AND user_info->'username' = %s
    """, (username,))
    if rec is not None:
        user_info = rec
    else:
        osm_user = requests.get("%s/user/%s" % (osm_api_url, username))
        if osm_user.status_code == 200:
            log("User %s found in OpenStreetMap but not in gittip." % username)
            user_info = None
        elif osm_user.status_code == 404:
            raise Response(404,
                           "OpenStreetMap identity '{0}' not found.".format(username))
        else:
            log("OpenStreetMap api responded with {0}: {1}".format(status, content),
                level=logging.WARNING)
            raise Response(502, "OpenStreetMap lookup failed with %d." % status)

    return user_info
コード例 #30
0
ファイル: payday.py プロジェクト: reedlaw/www.gittip.com
    def transfer(self, tipper, tippee, amount, pachinko=False):
        """Given two unicodes, a Decimal, and a boolean, return a boolean.

        If the tipper doesn't have enough in their Gittip account then we
        return False. Otherwise we decrement tipper's balance and increment
        tippee's *pending* balance by amount.

        """
        typecheck(tipper, unicode, tippee, unicode, amount, Decimal, pachinko,
                  bool)
        with self.db.get_cursor() as cursor:

            try:
                self.debit_participant(cursor, tipper, amount)
            except IntegrityError:
                return False

            self.credit_participant(cursor, tippee, amount)
            self.record_transfer(cursor, tipper, tippee, amount)
            if pachinko:
                self.mark_pachinko(cursor, amount)
            else:
                self.mark_transfer(cursor, amount)

            return True
コード例 #31
0
ファイル: utils.py プロジェクト: arkidas/www.gittip.com
def wrap(u):
    """Given a unicode, return a unicode.
    """
    typecheck(u, unicode)
    u = linkify(u)  # Do this first, because it calls xthml_escape.
    u = u.replace(u'\r\n', u'<br />\r\n').replace(u'\n', u'<br />\n')
    return u if u else '...'
コード例 #32
0
def clear(participant_id, stripe_customer_id):
    typecheck(participant_id, unicode, stripe_customer_id, unicode)

    # "Unlike other objects, deleted customers can still be retrieved through
    # the API, in order to be able to track the history of customers while
    # still removing their credit card details and preventing any further
    # operations to be performed" https://stripe.com/docs/api#delete_customer
    #
    # Hmm ... should we protect against that in associate (above)?
    # 
    # What this means though is (I think?) that we'll continue to be able to
    # search for customers in the Stripe management UI by participant_id (which
    # is stored as description in associate) even after the association is lost
    # in our own database. This should be helpful for customer support.

    customer = stripe.Customer.retrieve(stripe_customer_id)
    customer.delete()

    CLEAR = """\

        UPDATE participants
           SET stripe_customer_id=NULL
             , last_bill_result=NULL
         WHERE id=%s

    """
    db.execute(CLEAR, (participant_id,))
コード例 #33
0
def clear(db, thing, username, balanced_customer_href):
    typecheck( thing, unicode
             , username, unicode
             , balanced_customer_href, (unicode, str)
              )
    invalidate_on_balanced(thing, balanced_customer_href)
    store_result(db, thing, username, None)
コード例 #34
0
ファイル: payday.py プロジェクト: kaverna/www.gittip.com
    def charge(self, participant, amount):
        """Given dict and Decimal, return None.

        This is the only place where we actually charge credit cards. Amount
        should be the nominal amount. We'll compute Gittip's fee below this
        function and add it to amount to end up with charge_amount.

        """
        typecheck(participant, Participant, amount, Decimal)

        username = participant.username
        balanced_customer_href = participant.balanced_customer_href

        typecheck(username, unicode, balanced_customer_href, (unicode, None))

        # Perform some last-minute checks.
        # ================================

        if balanced_customer_href is None:
            self.mark_missing_funding()
            return  # Participant has no funding source.

        if not is_whitelisted(participant):
            return  # Participant not trusted.

        # Go to Balanced.
        # ===============

        things = self.charge_on_balanced(username, balanced_customer_href, amount)
        charge_amount, fee, error = things

        amount = charge_amount - fee  # account for possible rounding under
        # charge_on_*

        self.record_charge(amount, charge_amount, fee, error, username)
コード例 #35
0
    def get_img_src(self, size=128):
        """Return a value for <img src="..." />.

        Until we have our own profile pics, delegate. XXX Is this an attack
        vector? Can someone inject this value? Don't think so, but if you make
        it happen, let me know, eh? Thanks. :)

            https://www.gittip.com/security.txt

        """
        typecheck(size, int)

        src = '/assets/%s/avatar-default.gif' % os.environ['__VERSION__']

        github, twitter = self.get_accounts_elsewhere()
        if github is not None:
            # GitHub -> Gravatar: http://en.gravatar.com/site/implement/images/
            if 'gravatar_id' in github.user_info:
                gravatar_hash = github.user_info['gravatar_id']
                src = "https://www.gravatar.com/avatar/%s.jpg?s=%s"
                src %= (gravatar_hash, size)

        elif twitter is not None:
            # https://dev.twitter.com/docs/api/1/get/users/profile_image/%3Ascreen_name
            if 'profile_image_url_https' in twitter.user_info:
                src = twitter.user_info['profile_image_url_https']

                # For Twitter, we don't have good control over size. We don't
                # want the original, cause that can be huge. The next option is
                # 73px(?!).
                src = src.replace('_normal.', '_bigger.')

        return src
コード例 #36
0
ファイル: participant.py プロジェクト: dahlia/www.gittip.com
    def get_img_src(self, size=128):
        """Return a value for <img src="..." />.

        Until we have our own profile pics, delegate. XXX Is this an attack
        vector? Can someone inject this value? Don't think so, but if you make
        it happen, let me know, eh? Thanks. :)

            https://www.gittip.com/security.txt

        """
        typecheck(size, int)

        src = '/assets/%s/avatar-default.gif' % os.environ['__VERSION__']

        github, twitter, bitbucket = self.get_accounts_elsewhere()
        if github is not None:
            # GitHub -> Gravatar: http://en.gravatar.com/site/implement/images/
            if 'gravatar_id' in github.user_info:
                gravatar_hash = github.user_info['gravatar_id']
                src = "https://www.gravatar.com/avatar/%s.jpg?s=%s"
                src %= (gravatar_hash, size)

        elif twitter is not None:
            # https://dev.twitter.com/docs/api/1/get/users/profile_image/%3Ascreen_name
            if 'profile_image_url_https' in twitter.user_info:
                src = twitter.user_info['profile_image_url_https']

                # For Twitter, we don't have good control over size. We don't
                # want the original, cause that can be huge. The next option is
                # 73px(?!).
                src = src.replace('_normal.', '_bigger.')

        return src
コード例 #37
0
ファイル: request.py プロジェクト: BigBlueHat/aspen-python
    def __init__(self, headers, fp, server_software):
        """Takes a str, a file-like object, and another str.

        If the Mapping API is used (in/one/all/has), then the iterable will be
        read and parsed as media of type application/x-www-form-urlencoded or
        multipart/form-data, according to content_type.

        """
        typecheck(headers, Headers, server_software, str)
        raw_len = int(headers.get('Content-length', '') or '0')
        self.raw = self._read_raw(server_software, fp, raw_len)  # XXX lazy!
        parsed = self._parse(headers, self.raw)
        if parsed is None:
            # There was no content-type. Use self.raw.
            pass
        else:
            for k in parsed.keys():
                v = parsed[k]
                if isinstance(v, cgi.MiniFieldStorage):
                    v = v.value.decode("UTF-8")  # XXX Really? Always UTF-8?
                else:
                    assert isinstance(v, cgi.FieldStorage), v
                    if v.filename is None:
                        v = v.value.decode("UTF-8")
                self[k] = v
コード例 #38
0
ファイル: github.py プロジェクト: imathis/www.gittip.com
def get_user_info(login):
    """Get the given user's information from the DB or failing that, github.

    :param login:
        A unicode string representing a username in github.

    :returns:
        A dictionary containing github specific information for the user.
    """
    typecheck(login, unicode)
    rec = gittip.db.fetchone( "SELECT user_info FROM elsewhere "
                              "WHERE platform='github' "
                              "AND user_info->'login' = %s"
                            , (login,)
                             )
    if rec is not None:
        user_info = rec['user_info']
    else:
        url = "https://api.github.com/users/%s"
        user_info = requests.get(url % login)
        status = user_info.status_code
        content = user_info.text
        if status == 200:
            user_info = json.loads(content)
        elif status == 404:
            raise Response(404,
                           "GitHub identity '{0}' not found.".format(login))
        else:
            log("Github api responded with {0}: {1}".format(status, content),
                level=logging.WARNING)
            raise Response(502, "GitHub lookup failed with %d." % status)

    return user_info
コード例 #39
0
    def _get_renderer_factory(self, media_type, renderer):
        """Given two bytestrings, return a renderer factory or None.
        """
        typecheck(media_type, str, renderer, str)
        if renderer_re.match(renderer) is None:
            possible =', '.join(sorted(self.website.renderer_factories.keys()))
            msg = ("Malformed renderer %s. It must match %s. Possible "
                   "renderers (might need third-party libs): %s.")
            raise SyntaxError(msg % (renderer, renderer_re.pattern, possible))

        renderer = renderer.decode('US-ASCII')

        factories = self.website.renderer_factories
        make_renderer = factories.get(renderer, None)
        if isinstance(make_renderer, ImportError):
            raise make_renderer
        elif make_renderer is None:
            possible = []
            want_legend = False
            for k, v in sorted(factories.iteritems()):
                if isinstance(v, ImportError):
                    k = '*' + k
                    want_legend = True
                possible.append(k)
            possible = ', '.join(possible)
            if want_legend:
                legend = " (starred are missing third-party libraries)"
            else:
                legend = ''
            raise ValueError("Unknown renderer for %s: %s. Possible "
                             "renderers%s: %s."
                             % (media_type, renderer, legend, possible))
        return make_renderer
コード例 #40
0
ファイル: utils.py プロジェクト: lyndsysimon/www.gittip.com
def wrap(u):
    """Given a unicode, return a unicode.
    """
    typecheck(u, unicode)
    u = linkify(u)  # Do this first, because it calls xthml_escape.
    u = u.replace(u'\r\n', u'<br />\r\n').replace(u'\n', u'<br />\n')
    return u if u else '...'
コード例 #41
0
ファイル: __init__.py プロジェクト: alexcouper/www.gittip.com
def clear(thing, participant_id, balanced_account_uri):
    typecheck( thing, unicode
             , participant_id, unicode
             , balanced_account_uri, unicode
              )
    assert thing in ("credit card", "bank account"), thing


    # XXX Things in balanced cannot be deleted at the moment.
    # =======================================================
    # Instead we mark all valid cards as invalid which will restrict against
    # anyone being able to issue charges against them in the future.
    #
    # See: https://github.com/balanced/balanced-api/issues/22

    account = balanced.Account.find(balanced_account_uri)
    things = account.cards if thing == "credit card" else account.bank_accounts

    for _thing in things:
        if _thing.is_valid:
            _thing.is_valid = False
            _thing.save()

    CLEAR = """\

        UPDATE participants
           SET last_%s_result=NULL
         WHERE id=%%s

    """ % ("bill" if thing == "credit card" else "ach")
    gittip.db.execute(CLEAR, (participant_id,))
コード例 #42
0
ファイル: payday.py プロジェクト: Siecje/www.gittip.com
    def charge_on_balanced(self, username, balanced_customer_href, amount):
        """We have a purported balanced_customer_href. Try to use it.
        """
        typecheck( username, unicode
                 , balanced_customer_href, unicode
                 , amount, Decimal
                  )

        cents, msg, charge_amount, fee = self._prep_hit(amount)
        msg = msg % (username, "Balanced")

        try:
            customer = balanced.Customer.fetch(balanced_customer_href)
            customer.cards.one().debit(amount=cents, description=username)
            log(msg + "succeeded.")
            error = ""
        except balanced.exc.HTTPError as err:
            error = err.message.message
        except:
            error = repr(sys.exc_info()[1])

        if error:
            log(msg + "failed: %s" % error)

        return charge_amount, fee, error
コード例 #43
0
ファイル: __init__.py プロジェクト: mushketyk/www.gittip.com
def wrap(u):
    """Given a unicode, return a unicode.
    """
    typecheck(u, unicode)
    linkified = linkify(u)  # Do this first, because it calls xthml_escape.
    out = linkified.replace(u'\r\n', u'<br />\r\n').replace(u'\n', u'<br />\n')
    return out if out else '...'
コード例 #44
0
def get_user_info(username):
    """Get the given user's information from the DB or failing that, bitbucket.

    :param username:
        A unicode string representing a username in bitbucket.

    :returns:
        A dictionary containing bitbucket specific information for the user.
    """
    typecheck(username, unicode)
    rec = gittip.db.fetchone(
        "SELECT user_info FROM elsewhere "
        "WHERE platform='bitbucket' "
        "AND user_info->'username' = %s", (username, ))
    if rec is not None:
        user_info = rec['user_info']
    else:
        url = "%s/users/%s?pagelen=100"
        user_info = requests.get(url % (BASE_API_URL, username))
        status = user_info.status_code
        content = user_info.content
        if status == 200:
            user_info = json.loads(content)['user']
        elif status == 404:
            raise Response(
                404, "Bitbucket identity '{0}' not found.".format(username))
        else:
            log("Bitbucket api responded with {0}: {1}".format(
                status, content),
                level=logging.WARNING)
            raise Response(502, "Bitbucket lookup failed with %d." % status)

    return user_info
コード例 #45
0
def wrap(u):
    """Given a unicode, return a unicode.
    """
    typecheck(u, unicode)
    u = linkify(u)  # Do this first, because it calls xthml_escape.
    u = u.replace(u"\r\n", u"<br />\r\n").replace(u"\n", u"<br />\n")
    return u if u else "..."
コード例 #46
0
ファイル: __init__.py プロジェクト: alexcouper/www.gittip.com
def get_balanced_account(participant_id, balanced_account_uri):
    """Find or create a balanced.Account.
    """
    typecheck( participant_id, unicode
             , balanced_account_uri, (unicode, None)
              )

    # XXX Balanced requires an email address
    # https://github.com/balanced/balanced-api/issues/20

    email_address = '{}@gittip.com'.format(participant_id)

    if balanced_account_uri is None:
        try:
            account = \
               balanced.Account.query.filter(email_address=email_address).one()
        except balanced.exc.NoResultFound:
            account = balanced.Account(email_address=email_address).save()
        BALANCED_ACCOUNT = """\

                UPDATE participants
                   SET balanced_account_uri=%s
                 WHERE id=%s

        """
        gittip.db.execute(BALANCED_ACCOUNT, (account.uri, participant_id))
        account.meta['participant_id'] = participant_id
        account.save()  # HTTP call under here
    else:
        account = balanced.Account.find(balanced_account_uri)
    return account
コード例 #47
0
def redact_pmt(pmt):
    """Given a unicode, redact it with Samurai.
    """
    typecheck(pmt, (unicode, None))
    if pmt is not None:
        pm = PaymentMethod(pmt)
        if pm['payment_method_token']:
            pm._payment_method.redact()
コード例 #48
0
ファイル: parse.py プロジェクト: prodigeni/aspen-python
def yes_no(s):
    typecheck(s, unicode)
    s = s.lower()
    if s in [u'yes', u'true', u'1']:
        return True
    if s in [u'no', u'false', u'0']:
        return False
    raise ValueError("must be either yes/true/1 or no/false/0")
コード例 #49
0
ファイル: twitter.py プロジェクト: prodigeni/www.gittip.com
def get_user_info(screen_name):
    """Given a unicode, return a dict.
    """
    typecheck(screen_name, (unicode, UnicodeWithParams))
    rec = gittip.db.one( "SELECT user_info FROM elsewhere "
                         "WHERE platform='twitter' "
                         "AND user_info->'screen_name' = %s"
                       , (screen_name,)
                        )

    if rec is not None:
        user_info = rec
    else:
        # Updated using Twython as a point of reference:
        # https://github.com/ryanmcgrath/twython/blob/master/twython/twython.py#L76
        oauth = OAuth1(
            # we do not have access to the website obj,
            # so let's grab the details from the env
            environ['TWITTER_CONSUMER_KEY'],
            environ['TWITTER_CONSUMER_SECRET'],
            environ['TWITTER_ACCESS_TOKEN'],
            environ['TWITTER_ACCESS_TOKEN_SECRET'],
        )

        url = "https://api.twitter.com/1.1/users/show.json?screen_name=%s"
        user_info = requests.get(url % screen_name, auth=oauth)

        # Keep an eye on our Twitter usage.
        # =================================

        rate_limit = user_info.headers['X-Rate-Limit-Limit']
        rate_limit_remaining = user_info.headers['X-Rate-Limit-Remaining']
        rate_limit_reset = user_info.headers['X-Rate-Limit-Reset']

        try:
            rate_limit = int(rate_limit)
            rate_limit_remaining = int(rate_limit_remaining)
            rate_limit_reset = int(rate_limit_reset)
        except (TypeError, ValueError):
            log( "Got weird rate headers from Twitter: %s %s %s"
               % (rate_limit, rate_limit_remaining, rate_limit_reset)
                )
        else:
            reset = datetime.datetime.fromtimestamp(rate_limit_reset, tz=utc)
            reset = to_age(reset)
            log( "Twitter API calls used: %d / %d. Resets %s."
               % (rate_limit - rate_limit_remaining, rate_limit, reset)
                )


        if user_info.status_code == 200:
            user_info = json.loads(user_info.text)
        else:
            log("Twitter lookup failed with %d." % user_info.status_code)
            raise Response(404)

    return user_info
コード例 #50
0
    def charge(self, participant, amount):
        """Given dict and Decimal, return None.

        This is the only place where we actually charge credit cards. Amount
        should be the nominal amount. We'll compute Gittip's fee below this
        function and add it to amount to end up with charge_amount.

        """
        typecheck(participant, RealDictRow, amount, Decimal)

        participant_id = participant['id']
        balanced_account_uri = participant['balanced_account_uri']
        stripe_customer_id = participant['stripe_customer_id']

        typecheck( participant_id, unicode
                 , balanced_account_uri, (unicode, None)
                 , stripe_customer_id, (unicode, None)
                  )


        # Perform some last-minute checks.
        # ================================

        if balanced_account_uri is None and stripe_customer_id is None:
            self.mark_missing_funding()
            return      # Participant has no funding source.

        if not is_whitelisted(participant):
            return      # Participant not trusted.


        # Go to Balanced or Stripe.
        # =========================

        if balanced_account_uri is not None:
            things = self.charge_on_balanced( participant_id
                                            , balanced_account_uri
                                            , amount
                                             )
            charge_amount, fee, error = things
        else:
            assert stripe_customer_id is not None
            things = self.charge_on_stripe( participant_id
                                          , stripe_customer_id
                                          , amount
                                           )
            charge_amount, fee, error = things

        amount = charge_amount - fee  # account for possible rounding under
                                      # charge_on_*

        self.record_charge( amount
                          , charge_amount
                          , fee
                          , error
                          , participant_id
                           )
コード例 #51
0
 def update_goal(self, goal):
     typecheck(goal, (Decimal, None))
     with self.db.get_cursor() as c:
         tmp = goal if goal is None else unicode(goal)
         add_event(c, 'participant',
                   dict(id=self.id, action='set', values=dict(goal=tmp)))
         c.one(
             "UPDATE participants SET goal=%s WHERE username=%s RETURNING id",
             (goal, self.username))
     self.set_attributes(goal=goal)
コード例 #52
0
    def prep(self, amount):
        """Given a dollar amount as a string, return a 3-tuple.

        The return tuple is like the one returned from _prep_hit, but with the
        second value, a log message, removed.

        """
        typecheck(amount, unicode)
        out = list(_prep_hit(D(amount)))
        out = [out[0]] + out[2:]
        return tuple(out)
コード例 #53
0
def store_error(thing, participant_id, msg):
    typecheck(thing, unicode, participant_id, unicode, msg, unicode)
    assert thing in ("credit card", "bank account"), thing
    ERROR = """\

        UPDATE participants
           SET last_%s_result=%%s
         WHERE id=%%s

    """ % ("bill" if thing == "credit card" else "ach")
    gittip.db.execute(ERROR, (msg, participant_id))
コード例 #54
0
def store_error(db, thing, username, msg):
    typecheck(thing, unicode, username, unicode, msg, unicode)
    assert thing in ("credit card", "bank account"), thing
    ERROR = """\

        UPDATE participants
           SET last_%s_result=%%s
         WHERE username=%%s

    """ % ("bill" if thing == "credit card" else "ach")
    db.run(ERROR, (msg, username))
コード例 #55
0
def prep(amount):
    """Given a dollar amount as a string, return a 3-tuple.

    The return tuple is like the one returned from _prep_hit, but with the
    second value, a log message, removed.

    """
    typecheck(amount, unicode)
    payday = Payday(gittip.db)
    out = list(payday._prep_hit(Decimal(amount)))
    out = [out[0]] + out[2:]
    return tuple(out)
コード例 #56
0
def clear(thing, username, balanced_account_uri):
    typecheck(thing, unicode, username, unicode, balanced_account_uri, unicode)
    assert thing in ("credit card", "bank account"), thing
    invalidate_on_balanced(thing, balanced_account_uri)
    CLEAR = """\

        UPDATE participants
           SET last_%s_result=NULL
         WHERE username=%%s

    """ % ("bill" if thing == "credit card" else "ach")
    gittip.db.execute(CLEAR, (username, ))
コード例 #57
0
ファイル: __init__.py プロジェクト: yuyong0621/www.gittip.com
def clear(db, thing, username, balanced_customer_href):
    typecheck(thing, unicode, username, unicode, balanced_customer_href,
              (unicode, str))
    assert thing in ("credit card", "bank account"), thing
    invalidate_on_balanced(thing, balanced_customer_href)
    CLEAR = """\

        UPDATE participants
           SET last_%s_result=NULL
         WHERE username=%%s

    """ % ("bill" if thing == "credit card" else "ach")
    db.run(CLEAR, (username, ))
コード例 #58
0
ファイル: dispatcher.py プロジェクト: prodigeni/aspen-python
def _typecast(key, value):
    """Given two unicodes, return a unicode, and an int or unicode.
    """
    typecheck(key, (unicode, PathPart), value, (unicode, PathPart))
    debug(lambda: "typecasting " + key + ", " + value)
    if key.endswith('.int'):  # you can typecast to int
        key = key[:-4]
        try:
            value = int(value)
        except ValueError:
            raise Response(404)
    debug(lambda: "typecasted " + key + ", " + repr(value))
    return key, value
コード例 #59
0
    def __init__(self, user_id, user_info=None):
        """Takes a user_id and user_info, and updates the database.
        """
        typecheck(user_id, (int, unicode), user_info, (None, dict))
        self.user_id = unicode(user_id)

        if user_info is not None:
            a, b, c, d = self.upsert(user_info)

            self.participant_id = a
            self.is_claimed = b
            self.is_locked = c
            self.balance = d