Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    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()
Exemplo n.º 3
0
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))
Exemplo n.º 4
0
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))