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 create_contribution(event, contrib_data, custom_fields_data=None, session_block=None, extend_parent=False): start_dt = contrib_data.pop('start_dt', None) contrib = Contribution(event_new=event) contrib.populate_from_dict(contrib_data) if start_dt is not None: schedule_contribution(contrib, start_dt=start_dt, session_block=session_block, extend_parent=extend_parent) if custom_fields_data: set_custom_fields(contrib, custom_fields_data) db.session.flush() signals.event.contribution_created.send(contrib) logger.info('Contribution %s created by %s', contrib, session.user) contrib.event_new.log(EventLogRealm.management, EventLogKind.positive, 'Contributions', 'Contribution "{}" has been created'.format(contrib.title), session.user) return contrib
def _process(self): inherited_location = self.event.location_data inherited_location['inheriting'] = True default_duration = contribution_settings.get(self.event, 'default_duration') contrib_form_class = make_contribution_form(self.event) form = contrib_form_class(obj=FormDefaults( location_data=inherited_location, duration=default_duration), event=self.event) if form.validate_on_submit(): # Create empty contribution so it can be compared to the new one in flash_if_unregistered contrib = Contribution() with flash_if_unregistered(self.event, lambda: contrib.person_links): contrib = create_contribution(self.event, *get_field_values(form.data)) flash( _("Contribution '{}' created successfully").format( contrib.title), 'success') tpl_components = self.list_generator.render_list(contrib) if tpl_components['hide_contrib']: self.list_generator.flash_info_message(contrib) return jsonify_data(**tpl_components) return jsonify_template('events/contributions/forms/contribution.html', form=form)
def _migrate_event_reviewing(self, conf): conference_settings = getattr(conf, '_confPaperReview', None) if not conference_settings: return event = conf.as_event contrib_index = conference_settings._contribution_index = IOBTree() contrib_reviewers = _invert_mapping(conference_settings._reviewerContribution) contrib_referees = _invert_mapping(conference_settings._refereeContribution) contrib_editors = _invert_mapping(conference_settings._editorContribution) for old_contribution in conf.contributions.itervalues(): review_manager = getattr(old_contribution, '_reviewManager', None) new_contribution = Contribution.find_one(event_id=event.id, friendly_id=int(old_contribution.id)) cid = int(new_contribution.id) if review_manager: review_manager._contrib_id = cid contrib_index[cid] = review_manager self._migrate_contribution_roles(old_contribution, new_contribution, contrib_reviewers, PaperReviewingRoleType.reviewer, event.id) self._migrate_contribution_roles(old_contribution, new_contribution, contrib_referees, PaperReviewingRoleType.referee, event.id) self._migrate_contribution_roles(old_contribution, new_contribution, contrib_editors, PaperReviewingRoleType.editor, event.id) self._migrate_reviewing_materials(old_contribution, new_contribution, review_manager, event.id)
def _process_args(self): RHPapersBase._process_args(self) self.contribution = Contribution.get_one( request.view_args['contrib_id'], is_deleted=False) self.paper = self.contribution.paper if self.paper is None and self.PAPER_REQUIRED: raise NotFound
def _create_contribution(title, duration): entry = Contribution(event_new=dummy_event_new, title=title, duration=duration) db.session.add(entry) db.session.flush() return entry
def _create_contribution(event, title, duration=timedelta(minutes=20), **kwargs): entry = Contribution(event=event, title=title, duration=duration, **kwargs) db.session.add(entry) db.session.flush() return entry
def update_data_vc_room(self, vc_room, data, is_new=False): super(RedirectorPlugin, self).update_data_vc_room(vc_room, data) for key in ['room_url_base']: if key in data: vc_room.data[key] = data.pop(key) contrib = Contribution.get(data['contribution']) cid = contrib.id if contrib else 0 vc_room.data['room_url'] = url_for_plugin( 'vc_redirector.vc_redirect', contrib_id=cid) flag_modified(vc_room, 'data')
def create_contribution(event, contrib_data, custom_fields_data=None, session_block=None, extend_parent=False): user = session.user if session else None start_dt = contrib_data.pop('start_dt', None) contrib = Contribution(event=event) contrib.populate_from_dict(contrib_data) if custom_fields_data: set_custom_fields(contrib, custom_fields_data) db.session.flush() if start_dt is not None: schedule_contribution(contrib, start_dt=start_dt, session_block=session_block, extend_parent=extend_parent) signals.event.contribution_created.send(contrib) logger.info('Contribution %s created by %s', contrib, user) contrib.log(EventLogRealm.management, EventLogKind.positive, 'Contributions', f'Contribution {contrib.verbose_title} has been created', user) # Note: If you ever add more stuff here that should run for any new contribution, make sure # to also add it to ContributionCloner.clone_single_contribution return contrib
def obj_deref(ref): """Returns the object identified by `ref`""" from indico_livesync.models.queue import EntryType if ref['type'] == EntryType.category: return CategoryManager().getById(ref['category_id'], True) elif ref['type'] == EntryType.event: return Event.get(ref['event_id']) elif ref['type'] == EntryType.contribution: return Contribution.get(ref['contrib_id']) elif ref['type'] == EntryType.subcontribution: return SubContribution.get(ref['subcontrib_id']) else: raise ValueError('Unexpected object type: {}'.format(ref['type']))
def _checkParams(self): data = request.json self.object = None if 'categId' in data: self.object = Category.get_one(data['categId']) elif 'contribId' in data: self.object = Contribution.get_one(data['contribId']) elif 'sessionId' in data: self.object = Session.get_one(data['sessionId']) elif 'confId' in data: self.object = Event.get_one(data['confId']) if self.object is None: raise BadRequest
def _process_args(self): data = request.json self.object = None if 'categId' in data: self.object = Category.get_or_404(data['categId']) elif 'contribId' in data: self.object = Contribution.get_or_404(data['contribId']) elif 'sessionId' in data: self.object = Session.get_or_404(data['sessionId']) elif 'eventId' in data: self.object = Event.get_or_404(data['eventId']) if self.object is None: raise BadRequest
def _process_args(self): data = request.json self.object = None if 'categId' in data: self.object = Category.get_one(data['categId']) elif 'contribId' in data: self.object = Contribution.get_one(data['contribId']) elif 'sessionId' in data: self.object = Session.get_one(data['sessionId']) elif 'confId' in data: self.object = Event.get_one(data['confId']) if self.object is None: raise BadRequest
def obj_deref(ref): """Returns the object identified by `ref`""" from indico_livesync.models.queue import EntryType if ref['type'] == EntryType.category: return Category.get_one(ref['category_id']) elif ref['type'] == EntryType.event: return Event.get_one(ref['event_id']) elif ref['type'] == EntryType.session: return Session.get_one(ref['session_id']) elif ref['type'] == EntryType.contribution: return Contribution.get_one(ref['contrib_id']) elif ref['type'] == EntryType.subcontribution: return SubContribution.get_one(ref['subcontrib_id']) else: raise ValueError('Unexpected object type: {}'.format(ref['type']))
def _process_cascaded_event_contents(records, additional_events=None): """ Flatten a series of records into its most basic elements (subcontribution level). Yields results. :param records: queue records to process :param additional_events: events whose content will be included in addition to those found in records """ changed_events = additional_events or set() changed_contributions = set() changed_subcontributions = set() session_records = {rec.session_id for rec in records if rec.type == EntryType.session} contribution_records = {rec.contrib_id for rec in records if rec.type == EntryType.contribution} subcontribution_records = {rec.subcontrib_id for rec in records if rec.type == EntryType.subcontribution} event_records = {rec.event_id for rec in records if rec.type == EntryType.event} if event_records: changed_events.update(Event.find(Event.id.in_(event_records))) for event in changed_events: yield event # Sessions are added (explicitly changed only, since they don't need to be sent anywhere) if session_records: changed_contributions.update(Contribution .find(Contribution.session_id.in_(session_records), ~Contribution.is_deleted)) # Contributions are added (implictly + explicitly changed) changed_event_ids = {ev.id for ev in changed_events} condition = Contribution.event_id.in_(changed_event_ids) & ~Contribution.is_deleted if contribution_records: condition = db.or_(condition, Contribution.id.in_(contribution_records)) contrib_query = Contribution.find(condition).options(joinedload('subcontributions')) for contribution in contrib_query: yield contribution changed_subcontributions.update(contribution.subcontributions) # Same for subcontributions if subcontribution_records: changed_subcontributions.update(SubContribution.find(SubContribution.id.in_(subcontribution_records))) for subcontrib in changed_subcontributions: yield subcontrib
def _handleGet(self): contributions = Contribution.find(event_new=self._conf.as_event, is_deleted=False).options( joinedload("timetable_entry"), joinedload("paper_reviewing_roles") ) filter = {} # filtering if the active user is a referee: he can only see his own contribs isOnlyReferee = ( RCReferee.hasRights(self) and not RCPaperReviewManager.hasRights(self) and not self._conf.canModify(self.getAW()) ) # We want to make an 'or', not an 'and' of the reviewing assign status filter["reviewing"] = {} if isOnlyReferee: filter["reviewing"]["referee"] = self._getUser() elif self._showWithReferee: filter["reviewing"]["referee"] = "any" if self._showWithEditor: filter["reviewing"]["editor"] = "any" if self._showWithReviewer: filter["reviewing"]["reviewer"] = "any" filter["type"] = self._selTypes filter["track"] = self._selTracks filter["session"] = self._selSessions filter["materialsubmitted"] = self._showWithMaterial filterCrit = ContributionsReviewingFilterCrit(self._conf, filter) sortingCrit = contribFilters.SortingCriteria(["number"]) filterCrit.getField("type").setShowNoValue(self._typeShowNoValue) filterCrit.getField("track").setShowNoValue(self._trackShowNoValue) filterCrit.getField("session").setShowNoValue(self._sessionShowNoValue) filterCrit.getField("reviewing").setShowNoValue(self._showWithoutTeam) filterCrit.getField("materialsubmitted").setShowNoValue(self._showWithoutMaterial) f = filters.SimpleFilter(filterCrit, sortingCrit) contributions = f.apply(contributions) return [_serialize_contribution(contrib) for contrib in contributions]
def _handleGet(self): contributions = (Contribution.find( event_new=self._conf.as_event, is_deleted=False).options(joinedload('timetable_entry'), joinedload('paper_reviewing_roles'))) filter = {} #filtering if the active user is a referee: he can only see his own contribs isOnlyReferee = RCReferee.hasRights(self) \ and not RCPaperReviewManager.hasRights(self) \ and not self._conf.canModify(self.getAW()) # We want to make an 'or', not an 'and' of the reviewing assign status filter["reviewing"] = {} if isOnlyReferee: filter["reviewing"]["referee"] = self._getUser() elif self._showWithReferee: filter["reviewing"]["referee"] = "any" if self._showWithEditor: filter["reviewing"]["editor"] = "any" if self._showWithReviewer: filter["reviewing"]["reviewer"] = "any" filter["type"] = self._selTypes filter["track"] = self._selTracks filter["session"] = self._selSessions filter["materialsubmitted"] = self._showWithMaterial filterCrit = ContributionsReviewingFilterCrit(self._conf, filter) sortingCrit = contribFilters.SortingCriteria(["number"]) filterCrit.getField("type").setShowNoValue(self._typeShowNoValue) filterCrit.getField("track").setShowNoValue(self._trackShowNoValue) filterCrit.getField("session").setShowNoValue(self._sessionShowNoValue) filterCrit.getField("reviewing").setShowNoValue(self._showWithoutTeam) filterCrit.getField("materialsubmitted").setShowNoValue( self._showWithoutMaterial) f = filters.SimpleFilter(filterCrit, sortingCrit) contributions = f.apply(contributions) return [_serialize_contribution(contrib) for contrib in contributions]
def _migrate_papers(self): contributions = { c.id: c for c in (Contribution.find(event_new=self.event).options( joinedload('legacy_paper_reviewing_roles'))) } if not hasattr(self.pr, '_contribution_index'): self.importer.print_warning( cformat('%{yellow!}Event has no contribution index!'), event_id=self.event.id) return for contrib_id, rm in self.pr._contribution_index.iteritems(): if contrib_id not in contributions: self.importer.print_warning( cformat('%{yellow!}Contribution {} not found in event' ).format(contrib_id), event_id=self.event.id) continue contribution = contributions[contrib_id] self._migrate_paper_roles(contribution) self._migrate_revisions(contribution, rm)
def RHredirectToExternal(contrib_id): contrib = Contribution.get_or_404(contrib_id) event = contrib.event if not session.user: flash(_("The vc link is only available to logged in users."), 'error') raise BadRequest(response=redirect(event.url)) vcas = contrib.vc_room_associations vca = None for _vca in vcas: vca = _vca if isinstance(vca.vc_room.plugin, RedirectorPlugin): break else: raise BadRequest(response=redirect(event.url)) if vca.data.get('only_registered_users') and \ not any([x[1] for x in get_event_regforms(event, session.user)]): flash(_("The vc link is only available to registered users."), 'error') raise BadRequest(response=redirect(event.url)) vcroom = vca.vc_room url = vcroom.data['room_url_base'] data = {'id': contrib.friendly_id, 'username': session.user.name} req = requests.post(url, json=data) if req.status_code != 200: flash('Error: The redirector did not succeed!', 'error') raise BadRequest(response=redirect(event.url)) res = req.json() if res['status'] != 'success': flash(_("Videoconference link:") + ' ' + res['message'], 'error') raise BadRequest(response=redirect(event.url)) return redirect(res['url'])
def get_category_timetable(categ_ids, start_dt, end_dt, detail_level='event', tz=utc, from_categ=None, grouped=True): """Retrieve time blocks that fall within a specific time interval for a given set of categories. :param categ_ids: iterable containing list of category IDs :param start_dt: start of search interval (``datetime``, expected to be in display timezone) :param end_dt: end of search interval (``datetime`` in expected to be in display timezone) :param detail_level: the level of detail of information (``event|session|contribution``) :param tz: the ``timezone`` information should be displayed in :param from_categ: ``Category`` that will be taken into account to calculate visibility :param grouped: Whether to group results by start date :returns: a dictionary containing timetable information in a structured way. See source code for examples. """ day_start = start_dt.astimezone(utc) day_end = end_dt.astimezone(utc) dates_overlap = lambda t: (t.start_dt >= day_start) & (t.start_dt <= day_end) items = defaultdict(lambda: defaultdict(list)) # first of all, query TimetableEntries/events that fall within # specified range of dates (and category set) events = _query_events(categ_ids, day_start, day_end) if from_categ: events = events.filter(Event.is_visible_in(from_categ)) for eid, tt_start_dt in events: if tt_start_dt: items[eid][tt_start_dt.astimezone(tz).date()].append(tt_start_dt) else: items[eid] = None # then, retrieve detailed information about the events event_ids = set(items) query = (Event.find(Event.id.in_(event_ids)) .options(subqueryload(Event.person_links).joinedload(EventPersonLink.person), joinedload(Event.own_room).noload('owner'), joinedload(Event.own_venue), joinedload(Event.category).undefer('effective_icon_data'), undefer('effective_protection_mode'))) scheduled_events = defaultdict(list) ongoing_events = [] events = [] for e in query: if grouped: local_start_dt = e.start_dt.astimezone(tz).date() local_end_dt = e.end_dt.astimezone(tz).date() if items[e.id] is None: # if there is no TimetableEntry, this means the event has not timetable on that interval for day in iterdays(max(start_dt.date(), local_start_dt), min(end_dt.date(), local_end_dt)): # if the event starts on this date, we've got a time slot if day.date() == local_start_dt: scheduled_events[day.date()].append((e.start_dt, e)) else: ongoing_events.append(e) else: for start_d, start_dts in items[e.id].viewitems(): scheduled_events[start_d].append((start_dts[0], e)) else: events.append(e) # result['events'][date(...)] -> [(datetime(....), Event(...))] # result[event_id]['contribs'][date(...)] -> [(TimetableEntry(...), Contribution(...))] # result['ongoing_events'] = [Event(...)] if grouped: result = defaultdict(lambda: defaultdict(lambda: defaultdict(list))) else: result = defaultdict(lambda: defaultdict(list)) result.update({ 'events': scheduled_events if grouped else events, 'ongoing_events': ongoing_events }) # according to detail level, ask for extra information from the DB if detail_level != 'event': query = _query_blocks(event_ids, dates_overlap, detail_level) if grouped: for b in query: start_date = b.timetable_entry.start_dt.astimezone(tz).date() result[b.session.event_id]['blocks'][start_date].append((b.timetable_entry, b)) else: for b in query: result[b.session.event_id]['blocks'].append(b) if detail_level == 'contribution': query = (Contribution.find(Contribution.event_id.in_(event_ids), dates_overlap(TimetableEntry), ~Contribution.is_deleted) .options(contains_eager(Contribution.timetable_entry), joinedload(Contribution.person_links)) .join(TimetableEntry)) if grouped: for c in query: start_date = c.timetable_entry.start_dt.astimezone(tz).date() result[c.event_id]['contribs'][start_date].append((c.timetable_entry, c)) else: for c in query: result[c.event_id]['contributions'].append(c) query = (Break.find(TimetableEntry.event_id.in_(event_ids), dates_overlap(TimetableEntry)) .options(contains_eager(Break.timetable_entry)) .join(TimetableEntry)) if grouped: for b in query: start_date = b.timetable_entry.start_dt.astimezone(tz).date() result[b.timetable_entry.event_id]['breaks'][start_date].append((b.timetable_entry, b)) else: for b in query: result[b.timetable_entry.event_id]['breaks'].append(b) return result
def _migrate_contribution(self, old_contrib, friendly_id): ac = old_contrib._Contribution__ac try: description = old_contrib._fields.get('content', '') except AttributeError: if not self.is_legacy_event: self.print_warning('Contribution {} has no fields'.format(old_contrib)) description = '' description = convert_to_unicode(getattr(description, 'value', description)) # str or AbstractFieldContent status = getattr(old_contrib, '_status', None) status_class = status.__class__.__name__ if status else None contrib = Contribution(event_new=self.event, friendly_id=friendly_id, title=convert_to_unicode(old_contrib.title), render_mode=RenderMode.html, description=description, duration=old_contrib.duration, protection_mode=PROTECTION_MODE_MAP[ac._accessProtection], board_number=convert_to_unicode(getattr(old_contrib, '_boardNumber', '')), keywords=self._process_keywords(getattr(old_contrib, '_keywords', '')), is_deleted=(status_class == 'ContribStatusWithdrawn')) if old_contrib._track is not None: track = self.event_ns.track_map.get(old_contrib._track) if not track: self.print_warning('Track not found: {}. Setting to None.'.format(old_contrib._track)) else: contrib.track = track if not self.quiet: self.print_info('%[cyan]Contribution%[reset] {}'.format(contrib.title)) self.event_ns.legacy_contribution_map[old_contrib] = contrib contrib.legacy_mapping = LegacyContributionMapping(event_new=self.event, legacy_contribution_id=old_contrib.id) # contribution type if old_contrib._type is not None: try: contrib.type = self.event_ns.legacy_contribution_type_map[old_contrib._type] except AttributeError: self.print_warning('%[yellow!]Invalid contrib type {}' .format(convert_to_unicode(old_contrib._type._name))) # abstract if old_contrib in self.event_ns.legacy_contribution_abstracts: contrib.abstract = self.event_ns.legacy_contribution_abstracts[old_contrib] # ACLs (managers, read access, submitters) principals = {} self._process_ac(ContributionPrincipal, principals, ac) for submitter in old_contrib._submitters: self._process_principal(ContributionPrincipal, principals, submitter, 'Submitter', roles={'submit'}) self._process_principal_emails(ContributionPrincipal, principals, getattr(old_contrib, '_submittersEmail', []), 'Submitter', roles={'submit'}) contrib.acl_entries = set(principals.itervalues()) # speakers, authors and co-authors contrib.person_links = list(self._migrate_contribution_person_links(old_contrib)) # references ("report numbers") contrib.references = list(self._process_references(ContributionReference, old_contrib)) # contribution/abstract fields if hasattr(old_contrib, '_fields'): contrib.field_values = list(self._migrate_contribution_field_values(old_contrib)) contrib.subcontributions = [self._migrate_subcontribution(old_contrib, old_subcontrib, pos) for pos, old_subcontrib in enumerate(old_contrib._subConts, 1)] contrib._last_friendly_subcontribution_id = len(contrib.subcontributions) return contrib
def _checkParams(self, params): RHManageContributionsBase._checkParams(self, params) self.contrib = Contribution.find_one(id=request.view_args['contrib_id'], is_deleted=False)
def _process_args(self): RHConferenceBaseDisplay._process_args(self) self.contrib = Contribution.get_one(request.view_args['contrib_id'], is_deleted=False)
def _checkParams(self, params): RHConferenceBaseDisplay._checkParams(self, params) self.contrib = Contribution.get_one(request.view_args['contrib_id'], is_deleted=False)
def _process_args(self): RHPapersBase._process_args(self) self.contribution = Contribution.get_one(request.view_args['contrib_id'], is_deleted=False) self.paper = self.contribution.paper if self.paper is None and self.PAPER_REQUIRED: raise NotFound
def _process_cascaded_event_contents(records, additional_events=None): """ Flatten a series of records into its most basic elements (subcontribution level). Yields results. :param records: queue records to process :param additional_events: events whose content will be included in addition to those found in records """ changed_events = additional_events or set() changed_contributions = set() changed_subcontributions = set() session_records = { rec.session_id for rec in records if rec.type == EntryType.session } contribution_records = { rec.contrib_id for rec in records if rec.type == EntryType.contribution } subcontribution_records = { rec.subcontrib_id for rec in records if rec.type == EntryType.subcontribution } event_records = { rec.event_id for rec in records if rec.type == EntryType.event } if event_records: changed_events.update(Event.find(Event.id.in_(event_records))) for event in changed_events: yield event # Sessions are added (explicitly changed only, since they don't need to be sent anywhere) if session_records: changed_contributions.update( Contribution.find(Contribution.session_id.in_(session_records), ~Contribution.is_deleted)) # Contributions are added (implictly + explicitly changed) changed_event_ids = {ev.id for ev in changed_events} condition = Contribution.event_id.in_( changed_event_ids) & ~Contribution.is_deleted if contribution_records: condition = db.or_(condition, Contribution.id.in_(contribution_records)) contrib_query = Contribution.find(condition).options( joinedload('subcontributions')) for contribution in contrib_query: yield contribution changed_subcontributions.update(contribution.subcontributions) # Same for subcontributions if subcontribution_records: changed_subcontributions.update( SubContribution.find( SubContribution.id.in_(subcontribution_records))) for subcontrib in changed_subcontributions: yield subcontrib
def search_contribs(self, q, user, page, category_id, event_id, admin_override_enabled): # XXX: Ideally we would search in subcontributions as well, but our pagination # does not really work when we do not have a single unique ID contrib_filters = [ Contribution.title_matches(q) | Contribution.description_matches(q), ~Contribution.is_deleted, ~Event.is_deleted ] if category_id is not None: contrib_filters.append(Event.category_chain_overlaps(category_id)) if event_id is not None: contrib_filters.append(Contribution.event_id == event_id) query = (Contribution.query.filter(*contrib_filters).join( Contribution.event).options( load_only('id', 'session_id', 'event_id', 'protection_mode'), undefer(Contribution.effective_protection_mode), _apply_acl_entry_strategy( selectinload(Contribution.acl_entries), ContributionPrincipal), joinedload(Contribution.session).options( load_only('id', 'protection_mode', 'event_id'), selectinload(Session.acl_entries)), contains_eager('event').options( _apply_acl_entry_strategy(selectinload(Event.acl_entries), EventPrincipal)))) objs, pagenav = self._paginate(query, page, Contribution.id, user, admin_override_enabled) event_strategy = joinedload(Contribution.event) event_strategy.joinedload(Event.own_venue) event_strategy.joinedload(Event.own_room).options( raiseload('*'), joinedload('location')) event_strategy.undefer(Event.detailed_category_chain) session_strategy = joinedload(Contribution.session) session_strategy.joinedload(Session.own_venue) session_strategy.joinedload(Session.own_room).options( raiseload('*'), joinedload('location')) session_block_strategy = joinedload(Contribution.session_block) session_block_strategy.joinedload(SessionBlock.own_venue) session_block_strategy.joinedload(SessionBlock.own_room).options( raiseload('*'), joinedload('location')) session_block_session_strategy = session_block_strategy.joinedload( SessionBlock.session) session_block_session_strategy.joinedload(Session.own_venue) session_block_session_strategy.joinedload(Session.own_room).options( raiseload('*'), joinedload('location')) query = (Contribution.query.filter( Contribution.id.in_(c.id for c in objs)).options( selectinload(Contribution.person_links).joinedload( 'person').joinedload('user').load_only('is_system'), event_strategy, session_strategy, session_block_strategy, joinedload(Contribution.type), joinedload(Contribution.own_venue), joinedload(Contribution.own_room).options( raiseload('*'), joinedload('location')), joinedload(Contribution.timetable_entry), )) contribs_by_id = {c.id: c for c in query} contribs = [contribs_by_id[c.id] for c in objs] res = HTMLStrippingContributionSchema(many=True).dump(contribs) return pagenav, ContributionResultSchema(many=True).load(res)
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
def _process_args(self): RHManageContributionsBase._process_args(self) self.contrib = Contribution.find_one( id=request.view_args['contrib_id'], is_deleted=False)
def _get_event_path(self, data): if not (contrib := Contribution.get(data['contribution_id'])): return []
def _process_args(self): RHDisplayEventBase._process_args(self) self.contrib = Contribution.get_one(request.view_args['contrib_id'], is_deleted=False)
def _checkParams(self, params): RHManageContributionsBase._checkParams(self, params) self.contrib = Contribution.find_one( id=request.view_args['contrib_id'], is_deleted=False)
def _process_args(self): RHManageContributionsBase._process_args(self) self.contrib = Contribution.find_one(id=request.view_args['contrib_id'], is_deleted=False)
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 contribution(self): return Contribution.get(self._contrib_id)