def test_contrib_friendly_id(monkeypatch, dummy_event, create_contribution): counter = Incrementer() monkeypatch.setattr(contrib_module, 'increment_and_get', counter) contrib_1 = create_contribution(dummy_event, 'Contribution 1', timedelta(minutes=60)) assert contrib_1.friendly_id == 1 contrib_2 = create_contribution(dummy_event, 'Contribution 2', timedelta(minutes=60)) assert contrib_2.friendly_id == 2 assert counter == 2 # pre-allocate 8 friendly ids Contribution.allocate_friendly_ids(dummy_event, 8) assert g.friendly_ids[Contribution][dummy_event.id] == range(3, 11) assert counter == 10 for fid in g.friendly_ids[Contribution][dummy_event.id][:]: contrib = create_contribution(dummy_event, 'Contribution {}'.format(fid), timedelta(minutes=30)) assert contrib.friendly_id == fid # increment_and_get doesn't get called because the ids # have been pre-allocated assert counter == 10
def import_contributions_from_csv(event, f): """Import timetable contributions from a CSV file into an event.""" with csv_text_io_wrapper(f) as ftxt: reader = csv.reader(ftxt.read().splitlines()) contrib_data = [] for num_row, row in enumerate(reader, 1): try: start_dt, duration, title, first_name, last_name, affiliation, email = ( value.strip() for value in row) email = email.lower() except ValueError: raise UserValueError( _('Row {}: malformed CSV data - please check that the number of columns is correct' ).format(num_row)) try: parsed_start_dt = event.tzinfo.localize( dateutil.parser.parse(start_dt)) if start_dt else None except ValueError: raise UserValueError( _('Row {row}: can\'t parse date: "{date}"').format( row=num_row, date=start_dt)) try: parsed_duration = timedelta( minutes=int(duration)) if duration else None except ValueError: raise UserValueError( _("Row {row}: can't parse duration: {duration}").format( row=num_row, duration=duration)) if not title: raise UserValueError( _('Row {}: contribution title is required').format(num_row)) if email and not validate_email(email): raise UserValueError( _('Row {row}: invalid email address: {email}').format( row=num_row, email=email)) contrib_data.append({ 'start_dt': parsed_start_dt, 'duration': parsed_duration or timedelta(minutes=20), 'title': title, 'speaker': { 'first_name': first_name, 'last_name': last_name, 'affiliation': affiliation, 'email': email } }) # now that we're sure the data is OK, let's pre-allocate the friendly ids # for the contributions in question Contribution.allocate_friendly_ids(event, len(contrib_data)) contributions = [] all_changes = defaultdict(list) for contrib_fields in contrib_data: speaker_data = contrib_fields.pop('speaker') with track_time_changes() as changes: contribution = create_contribution(event, contrib_fields, extend_parent=True) contributions.append(contribution) for key, val in changes[event].items(): all_changes[key].append(val) email = speaker_data['email'] if not email: continue # set the information of the speaker person = get_event_person(event, speaker_data) link = ContributionPersonLink(person=person, is_speaker=True) link.populate_from_dict({ 'first_name': speaker_data['first_name'], 'last_name': speaker_data['last_name'], 'affiliation': speaker_data['affiliation'] }) contribution.person_links.append(link) return contributions, all_changes
def import_contributions_from_csv(event, f): """Import timetable contributions from a CSV file into an event.""" reader = csv.reader(f.read().splitlines()) contrib_data = [] for num_row, row in enumerate(reader, 1): try: start_dt, duration, title, first_name, last_name, affiliation, email = \ [to_unicode(value).strip() for value in row] email = email.lower() except ValueError: raise UserValueError(_('Row {}: malformed CSV data - please check that the number of columns is correct') .format(num_row)) try: parsed_start_dt = event.tzinfo.localize(dateutil.parser.parse(start_dt)) if start_dt else None except ValueError: raise UserValueError(_("Row {row}: can't parse date: \"{date}\"").format(row=num_row, date=start_dt)) try: parsed_duration = timedelta(minutes=int(duration)) if duration else None except ValueError: raise UserValueError(_("Row {row}: can't parse duration: {duration}").format(row=num_row, duration=duration)) if not title: raise UserValueError(_("Row {}: contribution title is required").format(num_row)) if email and not validate_email(email): raise UserValueError(_("Row {row}: invalid email address: {email}").format(row=num_row, email=email)) contrib_data.append({ 'start_dt': parsed_start_dt, 'duration': parsed_duration or timedelta(minutes=20), 'title': title, 'speaker': { 'first_name': first_name, 'last_name': last_name, 'affiliation': affiliation, 'email': email } }) # now that we're sure the data is OK, let's pre-allocate the friendly ids # for the contributions in question Contribution.allocate_friendly_ids(event, len(contrib_data)) contributions = [] all_changes = defaultdict(list) for contrib_fields in contrib_data: speaker_data = contrib_fields.pop('speaker') with track_time_changes() as changes: contribution = create_contribution(event, contrib_fields, extend_parent=True) contributions.append(contribution) for key, val in changes[event].viewitems(): all_changes[key].append(val) email = speaker_data['email'] if not email: continue # set the information of the speaker person = get_event_person(event, { 'firstName': speaker_data['first_name'], 'familyName': speaker_data['last_name'], 'affiliation': speaker_data['affiliation'], 'email': email }) link = ContributionPersonLink(person=person, is_speaker=True) link.populate_from_dict({ 'first_name': speaker_data['first_name'], 'last_name': speaker_data['last_name'], 'affiliation': speaker_data['affiliation'] }) contribution.person_links.append(link) return contributions, all_changes