def test_relationships_from_gsx_entry(
        self,
        entry_original: Dict[str, Dict[str, str]],
        entry_translation: Dict[str, Dict[str, str]],
        entry_edition: Dict[str, Dict[str, str]],
    ):
        assert Resource.relationships_from_gsx_entry(None) is None

        Resource.from_gsx_entry(entry_original)
        resource = Resource.relationships_from_gsx_entry(entry_original)
        assert resource is not None
        assert resource.relationships.count() == 0

        Resource.from_gsx_entry(entry_translation)
        resource = Resource.relationships_from_gsx_entry(entry_translation)
        assert resource is not None
        assert resource.relationships.count() == 1

        entry = defaultdict(defaultdict)
        entry["gsx$title"]["$t"] = "Discours sur le gouvernement"
        Resource.from_gsx_entry(entry)
        entry = defaultdict(defaultdict)
        entry["gsx$title"]["$t"] = "Discourses concerning government"
        Resource.from_gsx_entry(entry)

        Resource.from_gsx_entry(entry_edition)
        resource = Resource.relationships_from_gsx_entry(entry_edition)
        assert resource is not None
        assert resource.relationships.count() == 2
    def test_get_place_names(
        self,
        entry_original: Dict[str, Dict[str, str]],
        entry_translation: Dict[str, Dict[str, str]],
    ):
        resource = Resource.from_gsx_entry(entry_original)
        assert resource.get_place_names() == "Paris"

        resource = Resource.from_gsx_entry(entry_translation)
        assert resource.get_place_names() == "London"
    def test_is_original(
        self,
        entry_original: Dict[str, Dict[str, str]],
        entry_translation: Dict[str, Dict[str, str]],
    ):
        resource = Resource.from_gsx_entry(entry_original)
        assert resource.is_original() is True

        resource = Resource.from_gsx_entry(entry_translation)
        assert resource.is_original() is False
    def test_get_classification_edition(
        self,
        entry_original: Dict[str, Dict[str, str]],
        entry_translation: Dict[str, Dict[str, str]],
    ):
        resource = Resource.from_gsx_entry(entry_original)
        assert resource.get_classification_edition().lower() == "source-text"

        resource = Resource.from_gsx_entry(entry_translation)
        assert resource.get_classification_edition().lower() == "integral"
    def test_get_language_names(
        self,
        entry_original: Dict[str, Dict[str, str]],
        entry_translation: Dict[str, Dict[str, str]],
    ):
        resource = Resource.from_gsx_entry(entry_original)
        assert resource.get_language_names() == "French"

        resource = Resource.from_gsx_entry(entry_translation)
        assert resource.get_language_names() == "English"
    def test_get_authors_source_text(
        self,
        entry_original: Dict[str, Dict[str, str]],
        entry_translation: Dict[str, Dict[str, str]],
    ):
        resource = Resource.from_gsx_entry(entry_original)
        assert resource.get_authors_source_text() is None

        Resource.from_gsx_entry(entry_translation)
        resource = Resource.relationships_from_gsx_entry(entry_translation)
        authors = resource.get_authors_source_text()
        assert authors is not None
        assert "Constantin" in authors[0].name
    def test_get_source_texts(
        self,
        entry_original: Dict[str, Dict[str, str]],
        entry_translation: Dict[str, Dict[str, str]],
    ):
        original = Resource.from_gsx_entry(entry_original)
        assert original.get_source_texts() is None

        Resource.from_gsx_entry(entry_translation)
        translation = Resource.relationships_from_gsx_entry(entry_translation)
        source_texts = translation.get_source_texts()
        assert source_texts is not None
        assert "Les ruines" in source_texts[0].title.main_title
    def test_get_languages_source_text(
        self,
        entry_original: Dict[str, Dict[str, str]],
        entry_translation: Dict[str, Dict[str, str]],
    ):
        original = Resource.from_gsx_entry(entry_original)
        assert original.get_languages_source_text() is None

        Resource.from_gsx_entry(entry_translation)
        translation = Resource.relationships_from_gsx_entry(entry_translation)
        languages = translation.get_languages_source_text()
        assert languages is not None
        assert languages[0].label == "French"
    def test_get_authors(
        self,
        entry_original: Dict[str, Dict[str, str]],
        entry_edition: Dict[str, Dict[str, str]],
    ):
        resource = Resource.from_gsx_entry(entry_original)
        assert "Constantin" in resource.get_authors()

        resource = Resource.from_gsx_entry(entry_edition)
        authors = resource.get_authors()
        assert "Samson" in authors
        assert ";" in authors
        assert "Dalila" in authors
    def test__get_subjects(self, entry_original):
        doc = ResourceDocument()

        resource = Resource.from_gsx_entry(entry_original)

        assert len(doc._get_subjects(resource, ["fast-forms"])) == 0
        assert len(doc._get_subjects(resource, ["fast-topic"])) == 2
    def test__get_classifications(self, entry_original):
        doc = ResourceDocument()

        resource = Resource.from_gsx_entry(entry_original)

        assert len(doc._get_classifications(resource, "rt-ppt")) == 0
        assert len(doc._get_classifications(resource, "rt-tt")) == 0
        assert len(doc._get_classifications(resource, "rt-pt")) == 0
    def test__get_resource(self, entry_original):
        doc = ResourceDocument()

        resource = Resource.from_gsx_entry(entry_original)
        assert doc._get_resource(resource) == resource

        paratext = Resource.paratext_from_gsx_entry(entry_original, resource)
        assert doc._get_resource(paratext) == resource
    def test_get_date(self, entry_original: Dict[str, Dict[str, str]]):
        resource = Resource.from_gsx_entry(entry_original)
        assert resource.date is not None
        assert resource.get_date() is not None

        paratext = Resource.paratext_from_gsx_entry(entry_original, resource)
        assert paratext.date is None
        assert paratext.get_date() is not None
        assert paratext.get_date() == resource.get_date()
    def test_prepare_summary(self, entry_original):
        doc = ResourceDocument()

        resource = Resource.from_gsx_entry(entry_original)

        assert len(doc.prepare_summary(resource)) == 1

        resource.summary = "resource summary"
        assert len(doc.prepare_summary(resource)) == 2
    def test_prepare_subjects(self, entry_original):
        doc = ResourceDocument()

        resource = Resource.from_gsx_entry(entry_original)
        paratext = Resource.paratext_from_gsx_entry(entry_original, resource)

        assert len(doc.prepare_subjects(resource)) == 2

        paratext.subjects.add(search_term_or_none("fast-topic", "Operas"))
        assert len(doc.prepare_subjects(resource)) == 4
    def test_paratext_of(self, entry_original: Dict[str, Dict[str, str]]):
        resource = Resource.from_gsx_entry(entry_original)
        assert resource.is_paratext() is False
        assert resource.paratext_of() is None

        paratext = Resource.paratext_from_gsx_entry(entry_original, resource)
        assert paratext.is_paratext() is True

        paratext_of = paratext.paratext_of()
        assert paratext_of is not None
        assert paratext_of.id == resource.id
def resource_for_search(entry_search):
    # setup
    resource = Resource.from_gsx_entry(entry_search)

    yield resource

    # teardown
    if resource.id:
        for rr in resource.related_to.all():
            rr.resource.delete()

        resource.delete()
    def test_prepare_form_genre(self, entry_original):
        doc = ResourceDocument()

        resource = Resource.from_gsx_entry(entry_original)
        paratext = Resource.paratext_from_gsx_entry(entry_original, resource)

        assert len(doc.prepare_form_genre(resource)) == 0

        resource.subjects.add(search_term_or_none("fast-forms", "History"))
        assert len(doc.prepare_form_genre(resource)) == 2

        paratext.subjects.add(search_term_or_none("fast-forms", "Periodicals"))
        assert len(doc.prepare_form_genre(resource)) == 4
    def test_prepare_classifications_paratext(self, entry_original):
        doc = ResourceDocument()

        resource = Resource.from_gsx_entry(entry_original)
        paratext = Resource.paratext_from_gsx_entry(entry_original, resource)

        assert len(doc.prepare_classifications_paratext(resource)) == 0

        paratext.classifications.add(
            Classification(edition=search_term_or_none("rt-pt", "Preface")),
            bulk=False,
        )
        assert len(doc.prepare_classifications_paratext(resource)) == 3
    def test_prepare_title(self, entry_original):
        doc = ResourceDocument()

        resource = Resource.from_gsx_entry(entry_original)
        paratext = Resource.paratext_from_gsx_entry(entry_original, resource)

        assert len(doc.prepare_title(resource)) == 1

        paratext.title.main_title = "a different title"
        paratext.title.save()
        paratext.save()

        assert len(doc.prepare_title(resource)) == 2
    def test_prepare_languages(self, entry_original):
        doc = ResourceDocument()

        resource = Resource.from_gsx_entry(entry_original)
        paratext = Resource.paratext_from_gsx_entry(entry_original, resource)

        assert len(doc.prepare_languages(resource)) == 2

        paratext.languages.add(
            ResourceLanguage(
                language=search_term_or_none("iso639-2", "english")),
            bulk=False,
        )
        assert len(doc.prepare_languages(resource)) == 4
    def test_prepare_places(self, entry_original):
        doc = ResourceDocument()

        resource = Resource.from_gsx_entry(entry_original)
        assert "fictional_place" not in doc.prepare_places(resource)[0]

        place = resource.places.first()
        place.fictional_place = "mordor"
        place.save()

        prepared = doc.prepare_places(resource)[0]

        assert "(" in prepared["place"]["address"]
        assert prepared["fictional_place"] is not None
    def test_from_gsx_entry(
        self,
        entry_original: Dict[str, Dict[str, str]],
        entry_translation: Dict[str, Dict[str, str]],
        entry_edition: Dict[str, Dict[str, str]],
        organisation: Organisation,
        person: Person,
    ):
        assert Resource.from_gsx_entry(None) is None

        entry = defaultdict(defaultdict)
        entry["gsx$title"]["$t"] = ""
        assert Resource.from_gsx_entry(entry) is None

        entry["gsx$title"]["$t"] = "Work 1"
        assert Resource.from_gsx_entry(entry) is not None

        entry["gsx$authors"]["$t"] = f"{person.name}"
        resource = Resource.from_gsx_entry(entry)
        assert resource.contributions.first().agent.name == person.name

        entry["gsx$language"]["$t"] = "French [fr]; English [en]"
        resource = Resource.from_gsx_entry(entry)
        assert "French" in resource.get_language_names()

        entry_original["gsx$authors"]["$t"] = ""
        entry_original["gsx$organisation"]["$t"] = ""

        resource = Resource.from_gsx_entry(entry_original)
        assert resource is not None
        assert "ruines" in resource.title.main_title
        assert resource.date.date_display == "1791"
        assert "Paris" in resource.places.first().place.address

        entry_original["gsx$authors"]["$t"] = f"{person.name}"
        resource = Resource.from_gsx_entry(entry_original)
        assert resource.contributions.count() == 1

        entry_original["gsx$organisation"]["$t"] = f"{organisation.name}"
        resource = Resource.from_gsx_entry(entry_original)
        assert resource.contributions.count() == 2
    def test_prepare_classifications_translation(self, entry_original):
        doc = ResourceDocument()

        resource = Resource.from_gsx_entry(entry_original)
        paratext = Resource.paratext_from_gsx_entry(entry_original, resource)

        assert len(doc.prepare_classifications_translation(resource)) == 0

        resource.classifications.add(
            Classification(edition=search_term_or_none("rt-tt", "Integral")),
            bulk=False,
        )
        assert len(doc.prepare_classifications_translation(resource)) == 2

        paratext.classifications.add(
            Classification(edition=search_term_or_none("rt-tt", "Partial")),
            bulk=False,
        )
        assert len(doc.prepare_classifications_translation(resource)) == 4
    def test_prepare_contributions(self, entry_original, person):
        doc = ResourceDocument()

        resource = Resource.from_gsx_entry(entry_original)
        paratext = Resource.paratext_from_gsx_entry(entry_original, resource)

        assert len(doc.prepare_contributions(resource)) == 3

        person.name = "Anonymous Badger"
        person.save()

        contribution = Contribution(resource=resource, agent=person)
        contribution.save()
        contribution.roles.add(search_term_or_none("wikidata", "bookseller"))

        paratext.contributions.add(contribution, bulk=False)
        assert len(doc.prepare_contributions(resource)) == 4

        contribution = doc.prepare_contributions(resource)[2]
        assert contribution["agent"]["name"] == "Anonymous"
    def test_prepare_classifications_printing_publishing(self, entry_original):
        doc = ResourceDocument()

        resource = Resource.from_gsx_entry(entry_original)
        paratext = Resource.paratext_from_gsx_entry(entry_original, resource)

        assert len(
            doc.prepare_classifications_printing_publishing(resource)) == 0

        resource.classifications.add(
            Classification(edition=search_term_or_none("rt-ppt", "Forgeries")),
            bulk=False,
        )
        assert len(
            doc.prepare_classifications_printing_publishing(resource)) == 2

        paratext.classifications.add(
            Classification(edition=search_term_or_none("rt-ppt", "Piracies")),
            bulk=False,
        )
        assert len(
            doc.prepare_classifications_printing_publishing(resource)) == 4
    def test_is_translation(
        self,
        entry_original: Dict[str, Dict[str, str]],
        entry_translation: Dict[str, Dict[str, str]],
        entry_edition: Dict[str, Dict[str, str]],
    ):
        Resource.from_gsx_entry(entry_original)
        resource = Resource.relationships_from_gsx_entry(entry_original)
        assert resource.is_translation() is False

        Resource.from_gsx_entry(entry_translation)
        resource = Resource.relationships_from_gsx_entry(entry_translation)
        assert resource.is_translation() is True

        Resource.from_gsx_entry(entry_edition)
        resource = Resource.relationships_from_gsx_entry(entry_edition)
        assert resource.is_translation() is True
    def handle(self, *args, **options):
        url = options["url"][0]
        delete = options["delete"]

        with request.urlopen(url) as response:
            data = json.loads(response.read().decode())
            entries = data["feed"]["entry"]

            if delete:
                self.stdout.write(
                    self.style.WARNING("Deleting all resources..."))
                Resource.objects.all().delete()

            self.stdout.write("Importing resources...")
            for entry in entries:
                resource = Resource.from_gsx_entry(entry)
                if resource:
                    self.stdout.write(self.style.SUCCESS(f"- {resource}"))

            self.stdout.write("Importing resource relationships...")
            for entry in entries:
                resource = Resource.relationships_from_gsx_entry(entry)
                if resource:
                    self.stdout.write(self.style.SUCCESS(f"> {resource}"))
    def test_get_paratext(self, entry_original: Dict[str, Dict[str, str]]):
        resource = Resource.from_gsx_entry(entry_original)
        assert resource.get_paratext().count() == 1

        paratext = Resource.paratext_from_gsx_entry(entry_original, resource)
        assert paratext.get_paratext().count() == 0