SciPost Code Repository

Skip to content
Snippets Groups Projects
factories.py 13.2 KiB
Newer Older
__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
import datetime
import random
from string import ascii_lowercase
import factory
import pytz

from common.faker import LazyAwareDate, LazyRandEnum, fake

Jean-Sébastien Caux's avatar
Jean-Sébastien Caux committed
from common.helpers import (
    random_external_doi,
    random_external_journal_abbrev,
)
from faker import Faker
from funders.factories import FunderFactory, GrantFactory
from journals.constants import (
    CC_LICENSES,
    ISSUES_AND_VOLUMES,
    ISSUES_ONLY,
    JOURNAL_STRUCTURE,
    PUBLICATION_PUBLISHED,
)
from journals.models import journal
from journals.models.autogenerated_file import AutogeneratedFileContentTemplate
from journals.models.deposits import DOAJDeposit, Deposit, GenericDOIDeposit
from journals.models.resource import PublicationResource
from journals.models.submission_template import SubmissionTemplate
from journals.models.update import PublicationUpdate
from ontology.factories import SpecialtyFactory

from .models import Issue, Journal, Publication, Reference, Volume
class ReferenceFactory(factory.django.DjangoModelFactory):
    publication = factory.SubFactory("journals.factories.JournalPublicationFactory")
Jean-Sébastien Caux's avatar
Jean-Sébastien Caux committed
    reference_number = factory.LazyAttribute(
        lambda o: o.publication.references.count() + 1
    )
    identifier = factory.lazy_attribute(lambda n: random_external_doi())
Jean-Sébastien Caux's avatar
Jean-Sébastien Caux committed
    link = factory.Faker("uri")

    class Meta:
        model = Reference

    @factory.lazy_attribute
    def citation(self):
        faker = Faker()
Jean-Sébastien Caux's avatar
Jean-Sébastien Caux committed
        return "<em>{}</em> {} <b>{}</b>, {} ({})".format(
            faker.sentence(),
            random_external_journal_abbrev(),
            random.randint(1, 100),
            random.randint(1, 100),
Jean-Sébastien Caux's avatar
Jean-Sébastien Caux committed
            faker.year(),
        )
class JournalFactory(factory.django.DjangoModelFactory):
Jean-Sébastien Caux's avatar
Jean-Sébastien Caux committed
    college = factory.SubFactory("colleges.factories.CollegeFactory")
    name = factory.LazyAttributeSequence(
        lambda self, n: f"SciPost {self.college.name} {n}"
    )
    name_abbrev = factory.LazyAttribute(
        lambda self: "SciPost" + "".join([w[:2] for w in self.name.split()[1:]])
    )
    doi_label = factory.SelfAttribute("name_abbrev")
    issn = factory.Faker("numerify", text="########")
    structure = LazyRandEnum(JOURNAL_STRUCTURE)
    list_order = factory.LazyAttribute(lambda self: self.college.journals.count() + 1)

    active = True
    submission_allowed = True

    oneliner = factory.Faker("sentence")
    description = factory.Faker("paragraph")
    scope = factory.Faker("paragraph")
    acceptance_criteria = factory.Faker("paragraph")
    submission_insert = factory.Faker("paragraph")

    template_latex_tgz = factory.django.FileField()
    template_docx = factory.django.FileField()

    cost_info = {"default": 500}

    class Meta:
        model = Journal
        django_get_or_create = ("name", "doi_label")
    @classmethod
    def SciPostPhysics(cls):
        return cls(
            name="SciPost Physics",
            doi_label="SciPostPhys",
            structure=ISSUES_AND_VOLUMES,
        )

    @classmethod
    def SciPostPhysicsProc(cls):
        return cls(
            name="SciPost Physics Proceedings",
            doi_label="SciPostPhysProc",
            structure=ISSUES_ONLY,
        )

    @factory.post_generation
    def specialties(self, create, extracted, **kwargs):
        if not create:
            return
        if extracted:
            self.specialties.add(*extracted)
        else:
            specialties = SpecialtyFactory.create_batch(
                3, acad_field=self.college.acad_field
            )
            self.specialties.add(*specialties)


class VolumeFactory(factory.django.DjangoModelFactory):
    in_journal = factory.SubFactory(JournalFactory)
    number = factory.LazyAttribute(lambda self: self.in_journal.volumes.count() + 1)
    doi_label = factory.LazyAttribute(
        lambda self: f"{self.in_journal.doi_label}.{self.number}"
Jean-Sébastien Caux's avatar
Jean-Sébastien Caux committed
    )
    start_date = LazyAwareDate("date_time_this_decade")
    until_date = factory.LazyAttribute(
        lambda self: fake.aware.date_between(start_date=self.start_date, end_date="+1y")
Jean-Sébastien Caux's avatar
Jean-Sébastien Caux committed
    )

    class Meta:
        model = Volume
Jean-Sébastien Caux's avatar
Jean-Sébastien Caux committed
        django_get_or_create = ("in_journal", "number")


class IssueFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Issue
        abstract = True

    class Params:
        parent = None

    number = factory.LazyAttribute(lambda self: self.parent.issues.count() + 1)
Jean-Sébastien Caux's avatar
Jean-Sébastien Caux committed
    doi_label = factory.LazyAttribute(
        lambda self: "%s.%i" % (self.parent.doi_label, self.number)
Jean-Sébastien Caux's avatar
Jean-Sébastien Caux committed
    )
    slug = factory.LazyAttribute(
        lambda self: "issue-" + self.doi_label.replace(".", "-")
    )


class VolumeIssueFactory(IssueFactory):
    class Params:
        parent = factory.SubFactory(VolumeFactory)

    in_volume = factory.SelfAttribute("parent")
Jean-Sébastien Caux's avatar
Jean-Sébastien Caux committed

    start_date = factory.LazyAttribute(
        lambda self: Faker().date_time_between(
            start_date=self.parent.start_date,
            end_date=self.parent.until_date,
Jean-Sébastien Caux's avatar
Jean-Sébastien Caux committed
            tzinfo=pytz.UTC,
        )
    )
    until_date = factory.LazyAttribute(
        lambda self: fake.aware.date_between(start_date=self.start_date, end_date="+1y")
Jean-Sébastien Caux's avatar
Jean-Sébastien Caux committed
    )
    path = factory.LazyAttribute(
        lambda self: f"JOURNALS/{self.in_volume.in_journal.doi_label}/{self.in_volume.number}/{self.number}"
Jean-Sébastien Caux's avatar
Jean-Sébastien Caux committed
    )
class JournalIssueFactory(IssueFactory):
    class Params:
        parent = factory.SubFactory(JournalFactory, structure=ISSUES_ONLY)
    in_journal = factory.SelfAttribute("parent")

    path = factory.LazyAttribute(
        lambda self: f"JOURNALS/{self.in_journal.doi_label}/{self.number}"
Jean-Sébastien Caux's avatar
Jean-Sébastien Caux committed
    )
class BasePublicationFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Publication
        abstract = True
Jean-Sébastien Caux's avatar
Jean-Sébastien Caux committed
        django_get_or_create = ("accepted_submission",)
        exclude = ("pub_container",)

    @factory.lazy_attribute
    def pub_container(self):
        issue = getattr(self, "in_issue", None)
        journal = getattr(self, "in_journal", None)
        return issue or journal
    # Publication data
    # TODO: This should be a PublishedSubmissionFactory
    accepted_submission = factory.SubFactory(
        "submissions.factories.SubmissionFactory"  # , generate_publication=False
    )
    status = PUBLICATION_PUBLISHED

    @factory.lazy_attribute
    def paper_nr(self):
        if self.pub_container:
            return self.pub_container.publications.count() + 1
    # Core fields
    title = factory.SelfAttribute("accepted_submission.title")
    author_list = factory.SelfAttribute("accepted_submission.author_list")
    abstract = factory.SelfAttribute("accepted_submission.abstract")
    pdf_file = factory.django.FileField()
    # Ontology-based semantic linking
    acad_field = factory.SelfAttribute("accepted_submission.acad_field")
    approaches = factory.SelfAttribute("accepted_submission.approaches")
    @factory.post_generation
    def specialties(self, create, extracted, **kwargs):
        if not create:
            return
        self.specialties.add(*self.accepted_submission.specialties.all())

    @factory.post_generation
    def topics(self, create, extracted, **kwargs):
        if not create:
            return
        self.topics.add(*self.accepted_submission.topics.all())
    cc_license = LazyRandEnum(CC_LICENSES)
    @factory.post_generation
    def grants(self, create, extracted, **kwargs):
        if not create:
            return
        if extracted:
            self.grants.add(*extracted)
        grants = GrantFactory.create_batch(3)
        self.grants.add(*grants)

    @factory.post_generation
    def funders_generic(self, create, extracted, **kwargs):
Jorran de Wit's avatar
Jorran de Wit committed
        if not create:
            return
        if extracted:
            self.funders_generic.add(*extracted)

        funders_generic = FunderFactory.create_batch(3)
        self.funders_generic.add(*funders_generic)

    # Metadata
    metadata = {}
    metadata_xml = ""
    metadata_DOAJ = {}
    citedby = {}
    number_of_citations = 0

    @factory.lazy_attribute
    def doi_label(self):
        if self.pub_container:
            return self.pub_container.doi_label + "." + str(self.paper_nr).rjust(3, "0")

    # Date fields
    submission_date = factory.SelfAttribute("accepted_submission.submission_date")
    acceptance_date = factory.SelfAttribute("accepted_submission.latest_activity")
    publication_date = factory.SelfAttribute("accepted_submission.latest_activity")
    latest_activity = factory.SelfAttribute("accepted_submission.latest_activity")
    latest_citedby_update = factory.SelfAttribute("accepted_submission.latest_activity")
    latest_metadata_update = factory.SelfAttribute(
        "accepted_submission.latest_activity"
    )

    # @factory.post_generation
    # def generate_publication(self, create, extracted, **kwargs):
    #     if create and extracted is not False:
    #         return

    #     from journals.factories import PublicationFactory

    #     factory.RelatedFactory(
    #         PublicationFactory,
    #         "accepted_submission",
    #         title=self.title,
    #         author_list=self.author_list,
    #     )

    # @factory.post_generation
    # def author_relations(self, create, extracted, **kwargs):
    #     if not create:
    #         return

    #     # Append references
    #     for i in range(5):
    #         ReferenceFactory(publication=self)
    # Copy author data from Submission
    # for author in self.accepted_submission.authors.all():
    #     self.authors.create(publication=self, profile=author)
    # self.authors_claims.add(*self.accepted_submission.authors_claims.all())
    # self.authors_false_claims.add(*self.accepted_submission.authors_false_claims.all())


class JournalPublicationFactory(BasePublicationFactory):
    in_journal = factory.SubFactory(JournalFactory)


class VolumeIssuePublicationFactory(BasePublicationFactory):
    in_issue = factory.SubFactory(VolumeIssueFactory)
    in_journal = factory.SelfAttribute("in_issue.in_volume.in_journal")


class JournalIssuePublicationFactory(BasePublicationFactory):
    in_issue = factory.SubFactory(JournalIssueFactory)
    in_journal = factory.SelfAttribute("in_issue.in_journal")


class AutogeneratedFileContentTemplateFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = AutogeneratedFileContentTemplate

    journal = factory.SubFactory(JournalFactory)
    name = factory.Faker("word")
    description = factory.Faker("sentence", nb_words=3)
    content_template_string = factory.Faker("word")


class DepositFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Deposit
    publication = factory.SubFactory(JournalPublicationFactory)
    deposition_date = factory.SelfAttribute("publication.publication_date")
    timestamp = factory.LazyAttribute(
        lambda self: self.deposition_date.strftime("%Y%m%d%H%M%S")
    )
    deposit_successful = True
    response_text = ""
    doi_batch_id = factory.Faker("word")
    metadata_xml = ""
    metadata_xml_file = factory.django.FileField()
    response_text = ""


class DOAJDepositFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = DOAJDeposit

    publication = factory.SubFactory(JournalPublicationFactory)
    deposition_date = factory.SelfAttribute("publication.publication_date")
    timestamp = factory.LazyAttribute(
        lambda self: self.deposition_date.strftime("%Y%m%d%H%M%S")
    )
    deposit_successful = True
    metadata_DOAJ = {}
    metadata_DOAJ_file = factory.django.FileField()
    response_text = ""


class GenericDOIDepositFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = GenericDOIDeposit
        abstract = True

    deposition_date = LazyAwareDate("date_this_year")
    timestamp = factory.LazyAttribute(
        lambda self: self.deposition_date.strftime("%Y%m%d%H%M%S")
    )
    deposit_successful = True
    doi_batch_id = factory.Faker("word")
    metadata_xml = ""
    response = ""


class PublicationResourceFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = PublicationResource

    _type = LazyRandEnum(PublicationResource.TYPE_CHOICES)
    publication = factory.SubFactory(JournalPublicationFactory)
    url = factory.Faker("uri")
    comments = factory.Faker("sentence")
    deprecated = False


class SubmissionTemplateFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = SubmissionTemplate

    template_type = LazyRandEnum(SubmissionTemplate.TYPE_CHOICES)
    template_file = factory.django.FileField()
    journal = factory.SubFactory(JournalFactory)
    date = LazyAwareDate("date_this_year")
    instructions = factory.Faker("paragraph")


class PublicationUpdateFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = PublicationUpdate

    publication = factory.SubFactory(JournalPublicationFactory)
    number = factory.LazyAttribute(lambda self: self.publication.updates.count() + 1)
    update_type = LazyRandEnum(PublicationUpdate.TYPE_CHOICES)
    text = factory.Faker("paragraph")
    publication_date = factory.LazyAttribute(
        lambda self: fake.aware.date_between(
            start_date=self.publication.publication_date, end_date="+1y"
        )
    )
    doideposit_needs_updating = False
    doi_label = factory.LazyAttribute(
        lambda self: f"{self.publication.doi_label}.Upd.{self.number}"
    )