<commit_before>"""Defines a Participant class.
"""
import random
import re
import uuid
from decimal import Decimal

import gittip
from aspen import Response
from aspen.utils import typecheck
from psycopg2 import IntegrityError


ASCII_ALLOWED_IN_USERNAME = set("0123456789"
                                "abcdefghijklmnopqrstuvwxyz"
                                "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                                ".,-_;:@ ")


class NoParticipantId(Exception):
    """Represent a bug where we treat an anonymous user as a participant.
    """


class NeedConfirmation(Exception):
    """We need confirmation before we'll proceed.
    """

    def __init__(self, a, b, c):
        self.other_is_a_real_participant = a
        self.this_is_others_last_account_elsewhere = b
        self.we_already_have_that_kind_of_account = c
        self._all = (a, b, c)

    def __repr__(self):
        return "<NeedConfirmation: %r %r %r>" % self._all
    __str__ = __repr__

    def __eq__(self, other):
        return self._all == other._all

    def __ne__(self, other):
        return not self.__eq__(other)

    def __nonzero__(self):
        # bool(need_confirmation)
        A, B, C = self._all
        return A or C


def gen_random_usernames():
    """Yield up to 100 random usernames.
    """
    seatbelt = 0
    while 1:
        yield hex(int(random.random() * 16**12))[2:].zfill(12).decode('ASCII')
        seatbelt += 1
        if seatbelt > 100:
            raise StopIteration


def reserve_a_random_username(db=None):
    """Reserve and a random username.

    The returned value is guaranteed to have been reserved in the database.

    """
    if db is None:  # During take_over we want to use our own transaction.
        db = gittip.db

    for username in gen_random_usernames():
        try:
            db.run( "INSERT INTO participants (username, username_lower) "
                    "VALUES (%s, %s)"
                  , (username, username.lower())
                   )
        except IntegrityError:  # Collision, try again with another value.
            pass
        else:
            break

    return username


def require_username(func):
    # XXX This should be done with a metaclass, maybe?
    def wrapped(self, *a, **kw):
        if self.username is None:
            raise NoParticipantId("User does not participate, apparently.")
        return func(self, *a, **kw)
    return wrapped

<commit_msg>Fix up an API that actually used a cursor<commit_after>"""Defines a Participant class.
"""
import random
import re
import uuid
from decimal import Decimal

import gittip
from aspen import Response
from aspen.utils import typecheck
from psycopg2 import IntegrityError


ASCII_ALLOWED_IN_USERNAME = set("0123456789"
                                "abcdefghijklmnopqrstuvwxyz"
                                "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                                ".,-_;:@ ")


class NoParticipantId(Exception):
    """Represent a bug where we treat an anonymous user as a participant.
    """


class NeedConfirmation(Exception):
    """We need confirmation before we'll proceed.
    """

    def __init__(self, a, b, c):
        self.other_is_a_real_participant = a
        self.this_is_others_last_account_elsewhere = b
        self.we_already_have_that_kind_of_account = c
        self._all = (a, b, c)

    def __repr__(self):
        return "<NeedConfirmation: %r %r %r>" % self._all
    __str__ = __repr__

    def __eq__(self, other):
        return self._all == other._all

    def __ne__(self, other):
        return not self.__eq__(other)

    def __nonzero__(self):
        # bool(need_confirmation)
        A, B, C = self._all
        return A or C


def gen_random_usernames():
    """Yield up to 100 random usernames.
    """
    seatbelt = 0
    while 1:
        yield hex(int(random.random() * 16**12))[2:].zfill(12).decode('ASCII')
        seatbelt += 1
        if seatbelt > 100:
            raise StopIteration


def reserve_a_random_username(txn):
    """Reserve a random username.

    The returned value is guaranteed to have been reserved in the database.

    """
    for username in gen_random_usernames():
        try:
            txn.execute( "INSERT INTO participants (username, username_lower) "
                         "VALUES (%s, %s)"
                       , (username, username.lower())
                        )
        except IntegrityError:  # Collision, try again with another value.
            pass
        else:
            break

    return username


def require_username(func):
    # XXX This should be done with a metaclass, maybe?
    def wrapped(self, *a, **kw):
        if self.username is None:
            raise NoParticipantId("User does not participate, apparently.")
        return func(self, *a, **kw)
    return wrapped


{'fraction_non_alphanumeric': 0.0899854862119013, 'fraction_numerical': 0.011196350818992328, 'mean_word_length': 2.211717709720373, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, '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': '4853562', 'n_tokens_mistral': 1501, 'n_tokens_neox': 1396, 'n_words': 428}