def create_mock_abstract(event): """Create a mock abstract that can be used in previews. Brace for geek references. """ User = namedtuple('Author', ['first_name', 'last_name', 'title', 'full_name']) Track = namedtuple('Track', ['title']) Session = namedtuple('Session', ['title']) ContributionType = namedtuple('ContributionType', ['name']) Contribution = namedtuple('Contribution', ['title', 'track', 'session', 'type', 'locator']) Abstract = namedtuple('Abstract', ['friendly_id', 'title', 'event_new', 'submitter', 'contribution', 'primary_authors', 'secondary_authors', 'locator', 'judgment_comment', 'accepted_track', 'accepted_contrib_type', 'state', 'merged_into']) englert = User(full_name="Fran\xe7ois Englert", first_name="Fran\xe7ois", last_name="Englert", title="Prof.") brout = User(full_name="Robert Brout", first_name="Robert", last_name="Brout", title="Prof.") guralnik = User(full_name="Gerald Guralnik", first_name="Gerald", last_name="Guralnik", title="Prof.") hagen = User(full_name="Carl Hagen", first_name="Carl", last_name="Hagen", title="Prof.") kibble = User(full_name="Tom Kibble", first_name="Tom", last_name="Kibble", title="Prof.") higgs = User(full_name="Peter Higgs", first_name="Peter", last_name="Higgs", title="Prof.") track = Track(title=_("Higgs Fields")) session = Session(title=_("Higgs Fields Posters")) contribution_type = ContributionType(name=_("Poster")) contribution = Contribution(title="Broken Symmetry and the Mass of Gauge Vector Mesons", track=track, session=session, type=contribution_type, locator={'confId': -314, 'contrib_id': 1234}) target_abstract = Abstract(friendly_id=315, title="Broken Symmetry", accepted_track=track, accepted_contrib_type=contribution_type, event_new=event, submitter=brout, state=AbstractState.accepted, contribution=contribution, primary_authors=[englert, brout], secondary_authors=[guralnik, hagen, kibble, higgs], locator={'confId': -314, 'abstract_id': 1235}, judgment_comment='Vague but interesting!', merged_into=None) abstract = Abstract(friendly_id=314, title="Broken Symmetry and the Mass of Gauge Vector Mesons", accepted_track=track, accepted_contrib_type=contribution_type, event_new=event, submitter=brout, state=AbstractState.accepted, contribution=contribution, primary_authors=[englert, brout], secondary_authors=[guralnik, hagen, kibble, higgs], locator={'confId': -314, 'abstract_id': 1234}, judgment_comment='Vague but interesting!', merged_into=target_abstract) return abstract
def dummy_abstract(db, dummy_event, dummy_user, create_dummy_person): abstract = Abstract( friendly_id=314, title='Broken Symmetry and the Mass of Gauge Vector Mesons', event=dummy_event, submitter=dummy_user, locator={ 'event_id': -314, 'abstract_id': 1234 }, judgment_comment='Vague but interesting!') author1 = create_dummy_person(abstract, 'John', 'Doe', '*****@*****.**', 'ACME', UserTitle.mr, True, AuthorType.primary) author2 = create_dummy_person(abstract, 'Pocahontas', 'Silva', '*****@*****.**', 'ACME', UserTitle.prof, False, AuthorType.primary) coauthor1 = create_dummy_person(abstract, 'John', 'Smith', '*****@*****.**', 'ACME', UserTitle.dr, False, AuthorType.primary) abstract.person_links = [author1, author2, coauthor1] db.session.add(abstract) db.session.flush() return abstract
def test_notification_rules(mocker, abstract_objects, create_email_template, dummy_user, dummy_event): send_email = mocker.patch( 'indico.modules.events.abstracts.notifications.send_email') event, abstract, track, contrib_type = abstract_objects event.abstract_email_templates.append( create_email_template(event, 0, 'merge', 'merged poster for track', [{ 'state': [AbstractState.merged.value], 'track': [track.id] }], True)) send_abstract_notifications(abstract) assert send_email.call_count == 0 abstract.state = AbstractState.accepted abstract.judge = dummy_user abstract.judgment_dt = now_utc(False) abstract.accepted_track = track send_abstract_notifications(abstract) assert send_email.call_count == 0 abstract.state = AbstractState.merged abstract.merged_into = Abstract(title='test', submitter=dummy_user, event=dummy_event) abstract.accepted_track = None abstract.submitted_for_tracks = {track} send_abstract_notifications(abstract) assert send_email.call_count == 1
def create_abstract(event, abstract_data, custom_fields_data=None, send_notifications=False): abstract = Abstract(event=event, submitter=session.user) tracks = abstract_data.pop('submitted_for_tracks', None) attachments = abstract_data.pop('attachments', None) abstract.populate_from_dict(abstract_data) if tracks is not None: _update_tracks(abstract, tracks) if custom_fields_data: set_custom_fields(abstract, custom_fields_data) db.session.flush() if attachments: add_abstract_files(abstract, attachments['added'], log_action=False) signals.event.abstract_created.send(abstract) if send_notifications: send_abstract_notifications(abstract) logger.info('Abstract %s created by %s', abstract, session.user) abstract.event.log(EventLogRealm.reviewing, EventLogKind.positive, 'Abstracts', 'Abstract {} created'.format(abstract.verbose_title), session.user) return abstract
def _new_abstract(self, event): abstract = Abstract(event_new=event) db.session.flush() return abstract
def create_mock_abstract(event): """Create a mock abstract that can be used in previews. Brace for geek references. """ User = namedtuple('Author', ['first_name', 'last_name', 'title', 'full_name']) Track = namedtuple('Track', ['title']) Session = namedtuple('Session', ['title']) ContributionType = namedtuple('ContributionType', ['name']) Contribution = namedtuple('Contribution', ['title', 'track', 'session', 'type', 'locator']) Abstract = namedtuple('Abstract', ['friendly_id', 'title', 'event', 'submitter', 'contribution', 'primary_authors', 'secondary_authors', 'locator', 'judgment_comment', 'accepted_track', 'accepted_contrib_type', 'state', 'merged_into']) class _MockLocator(dict): def __init__(self, locator, **sublocators): super().__init__(locator) self._sublocators = sublocators def __getattr__(self, attr): try: return self._sublocators[attr] except KeyError: raise AttributeError englert = User(full_name='Fran\xe7ois Englert', first_name='Fran\xe7ois', last_name='Englert', title='Prof.') brout = User(full_name='Robert Brout', first_name='Robert', last_name='Brout', title='Prof.') guralnik = User(full_name='Gerald Guralnik', first_name='Gerald', last_name='Guralnik', title='Prof.') hagen = User(full_name='Carl Hagen', first_name='Carl', last_name='Hagen', title='Prof.') kibble = User(full_name='Tom Kibble', first_name='Tom', last_name='Kibble', title='Prof.') higgs = User(full_name='Peter Higgs', first_name='Peter', last_name='Higgs', title='Prof.') track = Track(title='Higgs Fields') session = Session(title='Higgs Fields Posters') contribution_type = ContributionType(name='Poster') contribution = Contribution(title='Broken Symmetry and the Mass of Gauge Vector Mesons', track=track, session=session, type=contribution_type, locator={'event_id': -314, 'contrib_id': 1234}) target_abstract = Abstract(friendly_id=315, title='Broken Symmetry', accepted_track=track, accepted_contrib_type=contribution_type, event=event, submitter=brout, state=AbstractState.accepted, contribution=contribution, primary_authors=[englert, brout], secondary_authors=[guralnik, hagen, kibble, higgs], locator=_MockLocator({'event_id': -314, 'abstract_id': 1235}, token={'event_id': -314, 'uuid': '12345678-9abc-def0-1234-56789abcdef0'}), judgment_comment='Vague but interesting!', merged_into=None) abstract = Abstract(friendly_id=314, title='Broken Symmetry and the Mass of Gauge Vector Mesons', accepted_track=track, accepted_contrib_type=contribution_type, event=event, submitter=brout, state=AbstractState.accepted, contribution=contribution, primary_authors=[englert, brout], secondary_authors=[guralnik, hagen, kibble, higgs], locator=_MockLocator({'event_id': -314, 'abstract_id': 1234}, token={'event_id': -314, 'uuid': '12345678-9abc-def0-1234-56789abcdef0'}), judgment_comment='Vague but interesting!', merged_into=target_abstract) return abstract
def _create_abstract(event, title, **kwargs): abstract = Abstract(event=event, title=title, **kwargs) db.session.add(abstract) db.session.flush() return abstract
def _migrate_abstract(self, old_abstract): submitter = self.user_from_legacy(old_abstract._submitter._user, system_user=True) submitted_dt = old_abstract._submissionDate modified_dt = (old_abstract._modificationDate if (submitted_dt - old_abstract._modificationDate) > timedelta(seconds=10) else None) description = getattr(old_abstract, '_fields', {}).get('content', '') description = convert_to_unicode( getattr(description, 'value', description)) # str or AbstractFieldContent type_ = old_abstract._contribTypes[0] type_id = None try: type_id = self.event_ns.legacy_contribution_type_map[ type_].id if type_ else None except KeyError: self.print_warning( 'Abstract {} - invalid contrib type {}, setting to None'. format(old_abstract._id, convert_to_unicode(getattr(type_, '_name', str(type_))))) abstract = Abstract(friendly_id=int(old_abstract._id), title=convert_to_unicode(old_abstract._title), description=description, submitter=submitter, submitted_dt=submitted_dt, submitted_contrib_type_id=type_id, submission_comment=convert_to_unicode( old_abstract._comments), modified_dt=modified_dt) self.print_info('%[white!]Abstract %[cyan]{}%[reset]: {}'.format( abstract.friendly_id, abstract.title)) self.event.abstracts.append(abstract) self.event_ns.abstract_map[old_abstract] = abstract accepted_type_id = None accepted_track_id = None old_contribution = getattr(old_abstract, '_contribution', None) if old_contribution: assert old_contribution.__class__.__name__ == 'AcceptedContribution' if old_abstract._currentStatus.__class__.__name__ == 'AbstractStatusAccepted': old_contrib_type = old_abstract._currentStatus._contribType try: accepted_type_id = ( self.event_ns. legacy_contribution_type_map[old_contrib_type].id if old_contrib_type else None) except KeyError: self.print_warning( '%[yellow!]Contribution {} - invalid contrib type {}, setting to None' .format(old_contribution.id, convert_to_unicode(old_contrib_type._name))) old_accepted_track = old_abstract._currentStatus._track accepted_track_id = int( old_accepted_track.id) if old_accepted_track else None if old_contribution and old_contribution.id is not None: self.event_ns.legacy_contribution_abstracts[ old_contribution] = abstract try: accepted_track = ( self.event_ns.track_map_by_id.get(accepted_track_id) if accepted_track_id is not None else None) except KeyError: self.print_error( '%[yellow!]Abstract #{} accepted in invalid track #{}'.format( abstract.friendly_id, accepted_track_id)) accepted_track = None # state old_state = old_abstract._currentStatus old_state_name = old_state.__class__.__name__ self.event_ns.old_abstract_state_map[abstract] = old_state abstract.state = self.STATE_MAP[old_state_name] if abstract.state == AbstractState.accepted: abstract.accepted_contrib_type_id = accepted_type_id abstract.accepted_track = accepted_track if abstract.state in self.JUDGED_STATES: abstract.judge = self.user_from_legacy(old_state._responsible, system_user=True) abstract.judgment_dt = as_utc(old_state._date) # files for old_attachment in getattr(old_abstract, '_attachments', {}).itervalues(): storage_backend, storage_path, size, md5 = self._get_local_file_info( old_attachment) if storage_path is None: self.print_error( '%[red!]File not found on disk; skipping it [{}]'.format( convert_to_unicode(old_attachment.fileName))) continue content_type = mimetypes.guess_type( old_attachment.fileName)[0] or 'application/octet-stream' filename = secure_filename( convert_to_unicode(old_attachment.fileName), 'attachment') attachment = AbstractFile(filename=filename, content_type=content_type, size=size, md5=md5, storage_backend=storage_backend, storage_file_id=storage_path) abstract.files.append(attachment) # internal comments for old_comment in old_abstract._intComments: comment = AbstractComment( user=self.user_from_legacy(old_comment._responsible, system_user=True), text=convert_to_unicode(old_comment._content), created_dt=old_comment._creationDate, modified_dt=old_comment._modificationDate) abstract.comments.append(comment) # tracks reallocated = set(r._track for r in getattr( old_abstract, '_trackReallocations', {}).itervalues()) for old_track in old_abstract._tracks.values(): abstract.reviewed_for_tracks.add( self.event_ns.track_map.get(old_track)) if old_track not in reallocated: abstract.submitted_for_tracks.add( self.event_ns.track_map.get(old_track)) # reviews/judgments self._migrate_abstract_reviews(abstract, old_abstract) # persons self._migrate_abstract_persons(abstract, old_abstract) # email log self._migrate_abstract_email_log(abstract, old_abstract) # contribution/abstract fields abstract.field_values = list( self._migrate_abstract_field_values(old_abstract)) return abstract
def _migrate_abstracts(self): old_by_id = {oa.friendly_id: oa for oa in self.event.old_abstracts} abstract_map = {} old_abstract_state_map = {} as_duplicate_reviews = set() for zodb_abstract in self.amgr._abstracts.itervalues(): old_abstract = old_by_id[int(zodb_abstract._id)] submitter = self._user_from_legacy(zodb_abstract._submitter._user, janitor=True) submitted_dt = zodb_abstract._submissionDate modified_dt = (zodb_abstract._modificationDate if (submitted_dt - zodb_abstract._modificationDate) > timedelta(seconds=10) else None) try: accepted_track = ( self.track_map_by_id[old_abstract.accepted_track_id] if old_abstract.accepted_track_id is not None else None) except KeyError: self.importer.print_error(cformat( '%{yellow!}Abstract #{} accepted in invalid track #{}' ).format(old_abstract.friendly_id, old_abstract.accepted_track_id), event_id=self.event.id) accepted_track = None abstract = Abstract(id=old_abstract.id, friendly_id=old_abstract.friendly_id, title=convert_to_unicode(zodb_abstract._title), description=old_abstract.description, submitter=submitter, submitted_dt=submitted_dt, submitted_contrib_type_id=old_abstract.type_id, submission_comment=convert_to_unicode( zodb_abstract._comments), modified_dt=modified_dt) self.importer.print_info( cformat('%{white!}Abstract:%{reset} {}').format( abstract.title)) self.event.abstracts.append(abstract) abstract_map[zodb_abstract] = abstract # files for old_attachment in getattr(zodb_abstract, '_attachments', {}).itervalues(): storage_backend, storage_path, size = self.importer._get_local_file_info( old_attachment) if storage_path is None: self.importer.print_error(cformat( '%{red!}File not found on disk; skipping it [{}]' ).format(convert_to_unicode(old_attachment.fileName)), event_id=self.event.id) continue content_type = mimetypes.guess_type( old_attachment.fileName)[0] or 'application/octet-stream' filename = secure_filename( convert_to_unicode(old_attachment.fileName), 'attachment') attachment = AbstractFile(filename=filename, content_type=content_type, size=size, storage_backend=storage_backend, storage_file_id=storage_path) abstract.files.append(attachment) # internal comments for old_comment in zodb_abstract._intComments: comment = AbstractComment( user=self._user_from_legacy(old_comment._responsible), text=convert_to_unicode(old_comment._content), created_dt=old_comment._creationDate, modified_dt=old_comment._modificationDate) abstract.comments.append(comment) # state old_state = zodb_abstract._currentStatus old_state_name = old_state.__class__.__name__ old_abstract_state_map[abstract] = old_state abstract.state = self.STATE_MAP[old_state_name] if abstract.state == AbstractState.accepted: abstract.accepted_contrib_type_id = old_abstract.accepted_type_id abstract.accepted_track = accepted_track if abstract.state in self.JUDGED_STATES: abstract.judge = self._user_from_legacy(old_state._responsible, janitor=True) abstract.judgment_dt = as_utc(old_state._date) # tracks reallocated = set(r._track for r in getattr( zodb_abstract, '_trackReallocations', {}).itervalues()) for old_track in zodb_abstract._tracks.values(): abstract.reviewed_for_tracks.add(self.track_map[old_track]) if old_track not in reallocated: abstract.submitted_for_tracks.add( self.track_map[old_track]) # judgments (reviews) self._migrate_abstract_reviews(abstract, zodb_abstract, old_abstract, as_duplicate_reviews) # persons self._migrate_abstract_persons(abstract, zodb_abstract) # email log self._migrate_abstract_email_log(abstract, zodb_abstract) # merges/duplicates for abstract in self.event.abstracts: old_state = old_abstract_state_map[abstract] if abstract.state == AbstractState.merged: abstract.merged_into = abstract_map[old_state._target] elif abstract.state == AbstractState.duplicate: abstract.duplicate_of = abstract_map[old_state._original] # mark-as-duplicate judgments for review, old_abstract in as_duplicate_reviews: try: review.proposed_related_abstract = abstract_map[old_abstract] except KeyError: self.importer.print_error(cformat( '%{yellow!}Abstract #{} marked as duplicate of invalid abstract #{}' ).format(review.abstract.friendly_id, old_abstract._id), event_id=self.event.id) # delete the review; it would violate our CHECKs review.abstract = None # not needed but avoids some warnings about the object not in the session review.track = None review.user = None