def test_store_events_with_classification(self): """Store events including classification.""" user = User(12345, '*****@*****.**') ev = CreateSubmission(creator=user) ev2 = SetPrimaryClassification(creator=user, category='physics.soc-ph') ev3 = AddSecondaryClassification(creator=user, category='physics.acc-ph') submission = ev.apply() submission = ev2.apply(submission) submission = ev3.apply(submission) with in_memory_db() as session: submission = classic.store_events(ev, ev2, ev3, submission=submission) db_submission = session.query(classic.models.Submission)\ .get(submission.submission_id) db_events = session.query(classic.DBEvent).all() self.assertEqual(db_submission.submission_id, submission.submission_id, "The submission should be updated with the PK id.") self.assertEqual(len(db_events), 3, "Three events should be stored") for db_event in db_events: self.assertEqual(db_event.submission_id, submission.submission_id, "The submission id should be set") self.assertEqual(len(db_submission.categories), 2, "Two category relations should be set") self.assertEqual(db_submission.primary_classification.category, submission.primary_classification.category, "Primary classification should be set.")
def test_get_submission_with_hold_and_reclass(self): """Test changes made externally are reflected in submission data.""" user = User(12345, '*****@*****.**') events = [ CreateSubmission(creator=user), UpdateMetadata(creator=user, metadata=[ ('title', 'Foo title'), ('abstract', 'Indeed'), ('authors', [ Author(order=0, forename='Joe', surname='Bloggs', email='*****@*****.**'), Author(order=1, forename='Jane', surname='Doe', email='*****@*****.**'), ]) ]), SelectLicense(creator=user, license_uri='http://foo.org/1.0/', license_name='Foo zero 1.0'), SetPrimaryClassification(creator=user, category='cs.DL'), AcceptPolicy(creator=user), VerifyContactInformation(creator=user), FinalizeSubmission(creator=user) ] submission = None for ev in events: submission = ev.apply(submission) if submission else ev.apply() with in_memory_db() as session: # User creates and finalizes submission. submission = classic.store_events(*events, submission=submission) ident = submission.submission_id # Moderation happens, things change outside the event model. db_submission = session.query(classic.models.Submission).get(ident) # Reclassification! session.delete(db_submission.primary_classification) session.add(classic.models.SubmissionCategory( submission_id=ident, category='cs.IR', is_primary=1 )) # On hold! db_submission.status = db_submission.ON_HOLD session.add(db_submission) session.commit() # Now get the submission. submission_loaded, _ = classic.get_submission(ident) self.assertEqual(submission.metadata.title, submission_loaded.metadata.title, "Event-derived metadata should be preserved.") self.assertEqual(submission_loaded.primary_classification.category, "cs.IR", "Primary classification should reflect the" " reclassification that occurred outside the purview" " of the event model.") self.assertEqual(submission_loaded.status, Submission.ON_HOLD, "Submission status should reflect hold action" " performed outside the purview of the event model.")
def test_get_submission_with_publish(self): """Test that publication state is reflected in submission data.""" user = User(12345, '*****@*****.**') events = [ CreateSubmission(creator=user), UpdateMetadata(creator=user, metadata=[ ('title', 'Foo title'), ('abstract', 'Indeed'), ('authors', [ Author(order=0, forename='Joe', surname='Bloggs', email='*****@*****.**'), Author(order=1, forename='Jane', surname='Doe', email='*****@*****.**'), ]) ]), SelectLicense(creator=user, license_uri='http://foo.org/1.0/', license_name='Foo zero 1.0'), SetPrimaryClassification(creator=user, category='cs.DL'), AcceptPolicy(creator=user), VerifyContactInformation(creator=user), FinalizeSubmission(creator=user) ] submission = None for ev in events: submission = ev.apply(submission) if submission else ev.apply() with in_memory_db() as session: # User creates and finalizes submission. submission = classic.store_events(*events, submission=submission) ident = submission.submission_id # Moderation happens, things change outside the event model. db_submission = session.query(classic.models.Submission).get(ident) # Published! db_submission.status = db_submission.PUBLISHED db_document = classic.models.Document(paper_id='1234.5678') db_submission.document = db_document session.add(db_submission) session.add(db_document) session.commit() # Now get the submission. submission_loaded, _ = classic.get_submission(ident) self.assertEqual(submission.metadata.title, submission_loaded.metadata.title, "Event-derived metadata should be preserved.") self.assertEqual(submission_loaded.arxiv_id, "1234.5678", "arXiv paper ID should be set") self.assertEqual(submission_loaded.status, Submission.PUBLISHED, "Submission status should reflect publish action")
def test_store_event(self): """Store a single event.""" with in_memory_db() as session: user = User(12345, '*****@*****.**') ev = CreateSubmission(creator=user) submission = ev.apply() submission = classic.store_events(ev, submission=submission) db_submission = session.query(classic.models.Submission)\ .get(submission.submission_id) self.assertEqual(db_submission.submission_id, submission.submission_id, "The submission should be updated with the PK id.") self.assertEqual(db_submission.submitter_id, submission.creator.native_id, "The native ID of the creator should be used") self.assertEqual(db_submission.status, db_submission.NOT_SUBMITTED, "Submission in database should be in status 0 (not" " submitted) by default.")
def test_store_events_with_finalized_submission(self): """Store events and a finalized submission.""" with in_memory_db() as session: user = User(12345, '*****@*****.**') ev = CreateSubmission(creator=user) ev2 = FinalizeSubmission(creator=user) submission = ev.apply() submission = ev2.apply(submission) submission = classic.store_events(ev, ev2, submission=submission) db_submission = session.query(classic.models.Submission)\ .get(submission.submission_id) db_events = session.query(classic.DBEvent).all() self.assertEqual(db_submission.submission_id, submission.submission_id, "The submission should be updated with the PK id.") self.assertEqual(len(db_events), 2, "Two events should be stored") for db_event in db_events: self.assertEqual(db_event.submission_id, submission.submission_id, "The submission id should be set")
def test_store_events_with_metadata(self): """Store events and attendant submission with metadata.""" metadata = { 'title': 'foo title', 'abstract': 'very abstract', 'comments': 'indeed', 'msc_class': 'foo msc', 'acm_class': 'computer-y', 'doi': '10.01234/5678', 'journal_ref': 'Nature 1: 1', 'authors': [Author(order=0, forename='Joe', surname='Bloggs')] } with in_memory_db() as session: user = User(12345, '*****@*****.**') ev = CreateSubmission(creator=user) ev2 = UpdateMetadata(creator=user, metadata=list(metadata.items())) submission = ev.apply() submission = ev2.apply(submission) submission = classic.store_events(ev, ev2, submission=submission) db_submission = session.query(classic.models.Submission)\ .get(submission.submission_id) db_events = session.query(classic.DBEvent).all() for key, value in metadata.items(): if key == 'authors': continue self.assertEqual(getattr(db_submission, key), value, f"The value of {key} should be {value}") self.assertEqual(db_submission.authors, submission.metadata.authors_display, "The canonical author string should be used to" " update the submission in the database.") self.assertEqual(len(db_events), 2, "Two events should be stored") for db_event in db_events: self.assertEqual(db_event.submission_id, submission.submission_id, "The submission id should be set")
def save(*events: Event, submission_id: Optional[str] = None) \ -> Tuple[Submission, List[Event]]: """ Commit a set of new :class:`.Event`s for a submission. This will persist the events to the database, along with the final state of the submission, and generate external notification(s) on the appropriate channels. Parameters ---------- events : :class:`.Event` Events to apply and persist. submission_id : int The unique ID for the submission, if available. If not provided, it is expected that ``events`` includes a :class:`.CreateSubmission`. Returns ------- :class:`events.domain.submission.Submission` The state of the submission after all events (including rule-derived events) have been applied. Updated with the submission ID, if a :class:`.CreateSubmission` was included. list A list of :class:`.Event` instances applied to the submission. Note that this list may contain more events than were passed, if event rules were triggered. Raises ------ :class:`.NoSuchSubmission` Raised if ``submission_id`` is not provided and the first event is not a :class:`.CreateSubmission`, or ``submission_id`` is provided but no such submission exists. :class:`.InvalidEvent` If an invalid event is encountered, the entire operation is aborted and this exception is raised. :class:`.SaveError` There was a problem persisting the events and/or submission state to the database. """ if len(events) == 0: raise ValueError('Must pass at least one event') # Do some sanity checks before proceeding. for event in events: if submission_id is not None: if event.submission_id is None: event.submission_id = submission_id if event.submission_id != submission_id: raise InvalidEvent( event, "Can't mix events for multiple submissions") # We want to play events from the beginning. if submission_id is not None: existing_events = classic.get_events(submission_id) else: existing_events = [] combined = existing_events + list(events) # Load any relevant event rules for this submission. rules = [] # database.get_rules(submission_id) # Calculate the state of the submission from old and new events. submission, combined = _apply_events(combined, rules) # Update the submission ID to ensure the existing submission is updated. if submission.submission_id is None: submission.submission_id = submission_id # May still be None. # Persist in database; submission ID is updated after transaction. try: submission = classic.store_events(*combined, submission=submission) except classic.CommitFailed as e: logger.debug('Encountered CommitFailed exception: %s', str(e)) raise SaveError('Failed to store events') from e for event in combined: event.submission_id = submission.submission_id return submission, combined