def test_update_fragment(self): "a fragment of article data can be updated by adding it again with different content" # ensure we have something that resembles the ingest data self.assertEqual(models.ArticleFragment.objects.count(), 1) frag = logic.get(self.av, 'xml->json').fragment self.assertTrue('title' in frag) # now update it with some garbage data = {'title': 'pants-party'} logic.add(self.av, 'xml->json', data, pos=0, update=True) # ensure we've just destroyed our very important data frag = logic.get(self.av, 'xml->json').fragment self.assertEqual(frag, data)
def setUp(self): self.nom = 'revalidate' # publish four valid articles, ensure each is in different states fixture_list = [ '01968', # SET '16695', # RESET '20105', # UNSET '20125', # NOTSET ] self.msid1, self.msid2, self.msid3, self.msid4 = fixture_list self.version = '1' for msid in fixture_list: fixture_path = join(self.fixture_dir, 'ajson', 'elife-%s-v1.xml.json' % msid) ajson_ingestor.ingest_publish(json.load(open(fixture_path, 'r'))) # SET # remove the valid ajson so it gets set av = article_logic.article_version(self.msid1, self.version) av.article_json_v1 = av.article_json_v1_snippet = None av.save() # RESET # already valid, nothing to do # UNSET # ensure the fragment is now invalid av = article_logic.article_version(self.msid3, self.version) frag = logic.get(av, models.XML2JSON) frag.fragment['title'] = '' frag.save() # NOTSET # remove the valid article-json # ensure fragment is invalid and won't be set av = article_logic.article_version(self.msid4, self.version) av.article_json_v1 = av.article_json_v1_snippet = None av.save() frag = logic.get(av, models.XML2JSON) frag.fragment['title'] = '' frag.save()
def _publish(msid, version, force=False): """attach a `datetime_published` value to an article version. if none provided, use RIGHT NOW. you cannot publish an already published article version unless force==True""" try: av = models.ArticleVersion.objects.get(article__manuscript_id=msid, version=version) if av.published(): if not force: raise StateError("refusing to publish an already published article version") # NOTE: we don't use any other article fragments for determining the publication date # except the xml->json fragment. raw_data = fragments.get(av, XML2JSON) # the json *will always* have a published date if v1 ... if version == 1: # pull that published date from the stored (but unpublished) article-json # and set the pub-date on the ArticleVersion object datetime_published = utils.todt(raw_data.get('published')) if not datetime_published: raise StateError("found 'published' value in article-json, but it's either null or unparsable as a datetime") else: # but *not* if it's > v1. in this case, we generate one. if av.published() and force: # this article version is already published and a force publish request has been sent if False and 'versionDate' in raw_data: # fail this case for now. # FUTURE CASE: when a 'versionDate' value is present in the article-json, use that. # as of 2016-10-21 version history IS NOT captured in the xml, # it won't be parsed by the bot-lax-adaptor and it # won't find it's way here. this is a future-case only. datetime_published = utils.todt(raw_data['versionDate']) if not datetime_published: raise StateError("found 'versionDate' value in article-json, but it's either null or unparseable as a datetime") else: # CURRENT CASE # preserve the existing pubdate set by lax. ignore anything given in the ajson. # if the pubdate for an article is to change, it must come from the xml (see above case) datetime_published = av.datetime_published else: # CURRENT CASE # this article version hasn't been published yet. use a value of RIGHT NOW as the published date. datetime_published = utils.utcnow() av.datetime_published = datetime_published av.save() # merge the fragments we have available and make them available for serving # allow errors when the publish operation is being forced fragments.merge_if_valid(av, quiet=force) # notify event bus that article change has occurred transaction.on_commit(partial(events.notify, av.article)) return av except ValidationError: raise StateError("refusing to publish an article '%sv%s' with invalid article-json" % (msid, version)) except models.ArticleFragment.DoesNotExist: raise StateError("no 'xml->json' fragment found. being strict and failing this publish. please INGEST!") except models.ArticleVersion.DoesNotExist: # attempted to publish an article that doesn't exist ... raise StateError("refusing to publish an article '%sv%s' that doesn't exist" % (msid, version))
def _publish(msid, version, force=False) -> models.ArticleVersion: """attach a `datetime_published` value to an article version. if none provided, use RIGHT NOW. you cannot publish an already published article version unless force==True""" try: av = models.ArticleVersion.objects.get(article__manuscript_id=msid, version=version) if av.published(): if not force: raise StateError( codes.ALREADY_PUBLISHED, "refusing to publish an already published article version") # NOTE: we don't use any other article fragments for determining the publication date # except the xml->json fragment. raw_data = fragments.get(av, XML2JSON).fragment # the json *will always* have a published date if v1 ... if version == 1: # pull that published date from the stored (but unpublished) article-json # and set the pub-date on the ArticleVersion object datetime_published = utils.todt(raw_data.get('published')) if not datetime_published: raise StateError( codes.PARSE_ERROR, "found 'published' value in article-json, but it's either null or unparsable as a date+time" ) else: # but *not* if it's > v1. in this case, we generate one. if av.published() and force: # this article version is already published and a force publish request has been sent if False and 'versionDate' in raw_data: # fail this case for now. # FUTURE CASE: when a 'versionDate' value is present in the article-json, use that. # as of 2016-10-21 version history IS NOT captured in the xml, # it won't be parsed by the bot-lax-adaptor and it # won't find it's way here. this is a future-case only. datetime_published = utils.todt(raw_data['versionDate']) if not datetime_published: raise StateError( codes.PARSE_ERROR, "found 'versionDate' value in article-json, but it's either null or unparseable as a datetime" ) else: # CURRENT CASE # preserve the existing pubdate set by lax. ignore anything given in the ajson. # if the pubdate for an article is to change, it must come from the xml (see above case) datetime_published = av.datetime_published else: # CURRENT CASE # this article version hasn't been published yet. use a value of RIGHT NOW as the published date. datetime_published = utils.utcnow() av.datetime_published = datetime_published av.save() events.ajson_publish_events(av, force) # merge the fragments we have available and make them available for serving. # allow errors when the publish operation is being forced. fragments.set_article_json( av, quiet=False if settings.VALIDATE_FAILS_FORCE else force) # notify event bus that article change has occurred transaction.on_commit(partial(aws_events.notify_all, av)) return av except ValidationError as err: # the problem isn't that the ajson is invalid, it's that we've allowed invalid ajson into the system raise StateError( codes.INVALID, "refusing to publish an article '%sv%s' with invalid article-json: %s" % (msid, version, err), err) except models.ArticleFragment.DoesNotExist: raise StateError( codes.NO_RECORD, "no 'xml->json' fragment found. being strict and failing this publish. please INGEST!" ) except models.ArticleVersion.DoesNotExist: # attempted to publish an article that doesn't exist ... raise StateError( codes.NO_RECORD, "refusing to publish an article '%sv%s' that doesn't exist" % (msid, version))