def test_srau_seatbelt_goes_to_100(self): def gen_test_username(): for i in range(100): yield 'deadbeef' def reserve(cursor, username): raise IntegrityError with self.db.get_cursor() as cursor: with pytest.raises(RanOutOfUsernameAttempts): safely_reserve_a_username(cursor, gen_test_username, reserve)
def test_srau_wears_a_seatbelt(self): def gen_test_username(): for i in range(101): yield 'deadbeef' def reserve(cursor, username): raise IntegrityError with self.db.get_cursor() as cursor: with pytest.raises(FailedToReserveUsername): safely_reserve_a_username(cursor, gen_test_username, reserve)
def test_srau_inserts_a_participant_by_default(self): def gen_test_username(): yield 'deadbeef' with self.db.get_cursor() as cursor: username = safely_reserve_a_username(cursor, gen_test_username) assert username == 'deadbeef' assert self.db.one('SELECT username FROM participants') == 'deadbeef'
def upsert(cls, i): """Insert or update a user's info. """ # Clean up avatar_url if i.avatar_url: scheme, netloc, path, query, fragment = urlsplit(i.avatar_url) fragment = '' if netloc.endswith('githubusercontent.com') or \ netloc.endswith('gravatar.com'): query = 's=128' i.avatar_url = urlunsplit((scheme, netloc, path, query, fragment)) # Serialize extra_info if isinstance(i.extra_info, ET.Element): i.extra_info = xmltodict.parse(ET.tostring(i.extra_info)) i.extra_info = json.dumps(i.extra_info) cols, vals = zip(*i.__dict__.items()) cols = ', '.join(cols) placeholders = ', '.join(['%s'] * len(vals)) try: # Try to insert the account # We do this with a transaction so that if the insert fails, the # participant we reserved for them is rolled back as well. with cls.db.get_cursor() as cursor: username = safely_reserve_a_username(cursor) cursor.execute( """ INSERT INTO elsewhere (participant, {0}) VALUES (%s, {1}) """.format(cols, placeholders), (username, ) + vals) # Propagate elsewhere.is_team to participants.number if i.is_team: cursor.execute( """ UPDATE participants SET number = 'plural'::participant_number WHERE username = %s """, (username, )) except IntegrityError: # The account is already in the DB, update it instead username = cls.db.one( """ UPDATE elsewhere SET ({0}) = ({1}) WHERE platform=%s AND user_id=%s RETURNING participant """.format(cols, placeholders), vals + (i.platform, i.user_id)) if not username: raise # Return account after propagating avatar_url to participant account = AccountElsewhere.from_user_id(i.platform, i.user_id) account.participant.update_avatar() return account
def test_srau_safely_reserves_a_username(self): def gen_test_username(): yield 'deadbeef' def reserve(cursor, username): return 'deadbeef' with self.db.get_cursor() as cursor: username = safely_reserve_a_username(cursor, gen_test_username, reserve) assert username == 'deadbeef' assert self.db.one('SELECT username FROM participants') is None
def test_srau_retries_work_with_db(self): # XXX This is raising InternalError because the transaction is ended or something. self.make_participant('deadbeef') def gen_test_username(): yield 'deadbeef' yield 'deafbeef' with self.db.get_cursor() as cursor: username = safely_reserve_a_username(cursor, gen_test_username) assert username == 'deafbeef'
def upsert(cls, i): """Insert or update a user's info. """ # Clean up avatar_url if i.avatar_url: scheme, netloc, path, query, fragment = urlsplit(i.avatar_url) fragment = "" if netloc.endswith("githubusercontent.com") or netloc.endswith("gravatar.com"): query = "s=128" i.avatar_url = urlunsplit((scheme, netloc, path, query, fragment)) # Serialize extra_info if isinstance(i.extra_info, ET.Element): i.extra_info = xmltodict.parse(ET.tostring(i.extra_info)) i.extra_info = json.dumps(i.extra_info) cols, vals = zip(*i.__dict__.items()) cols = ", ".join(cols) placeholders = ", ".join(["%s"] * len(vals)) try: # Try to insert the account # We do this with a transaction so that if the insert fails, the # participant we reserved for them is rolled back as well. with cls.db.get_cursor() as cursor: username = safely_reserve_a_username(cursor) cursor.execute( """ INSERT INTO elsewhere (participant, {0}) VALUES (%s, {1}) """.format( cols, placeholders ), (username,) + vals, ) # Propagate elsewhere.is_team to participants.number if i.is_team: cursor.execute( """ UPDATE participants SET number = 'plural'::participant_number WHERE username = %s """, (username,), ) except IntegrityError: # The account is already in the DB, update it instead username = cls.db.one( """ UPDATE elsewhere SET ({0}) = ({1}) WHERE platform=%s AND user_id=%s RETURNING participant """.format( cols, placeholders ), vals + (i.platform, i.user_id), ) if not username: raise # Return account after propagating avatar_url to participant account = AccountElsewhere.from_user_id(i.platform, i.user_id) account.participant.update_avatar() return account