def test_equality(self):
        """
        Tests that the equality of the objects is handled correctly
        :return: None
        """
        id_one = Id({IdType.MYANIMELIST: 1})
        id_two = Id({IdType.MYANIMELIST: 2})
        id_three = Id({IdType.MYANIMELIST: 3})

        one = Relation(id_one, MediaType.ANIME, id_two, MediaType.ANIME,
                       RelationType.SEQUEL)
        two = Relation(id_one, MediaType.ANIME, id_two, MediaType.ANIME,
                       RelationType.SEQUEL)
        three = Relation(id_one, MediaType.ANIME, id_three, MediaType.ANIME,
                         RelationType.SEQUEL)
        four = Relation(id_one, MediaType.ANIME, id_two, MediaType.ANIME,
                        RelationType.ADAPTATION)
        five = Relation(id_one, MediaType.ANIME, id_two, MediaType.MANGA,
                        RelationType.SEQUEL)

        self.assertNotEqual(one, "Test")
        self.assertEqual(one, two)
        self.assertNotEqual(two, three)
        self.assertNotEqual(two, four)
        self.assertNotEqual(three, four)
        self.assertNotEqual(one, five)
 def test_string_representation(self):
     """
     Tests that the string representation is correct
     :return: None
     """
     source = Id({IdType.MYANIMELIST: 1})
     dest = Id({IdType.MYANIMELIST: 2})
     relation = Relation(source, MediaType.ANIME, dest, MediaType.ANIME,
                         RelationType.SEQUEL)
     representation = str(relation)
     serialised = json.loads(representation)
     self.assertEqual(relation, Relation.deserialize(serialised))
    def _get_common_deserialized_components(
            cls,
            data: Dict[str, Optional[str or int or float or bool or
                                     Dict or List or Tuple or Set]]) \
            -> Dict[str, Optional[str or int or float or bool or
                                  Dict or List or Tuple or Set]]:
        """
        Deserializes the common child components of the data dictionary
        :param data: The data to deserialize
        :return: The deserialized dictionary
        """
        deserialized = {
            "media_type":
            MediaType[data["media_type"]],
            "id":
            Id.deserialize(data["id"]),
            "title":
            Title.deserialize(data["title"]),
            "relations":
            list(map(lambda x: Relation.deserialize(x), data["relations"])),
            "releasing_status":
            ReleasingStatus[data["releasing_status"]],
            "cover_url":
            data["cover_url"]
        }

        for date in ["releasing_start", "releasing_end"]:
            date_data = data[date]
            if date_data is not None:
                deserialized[date] = Date.deserialize(date_data)
            else:
                deserialized[date] = None

        return deserialized
 def test_generating_anime_media_list_entry(self):
     """
     Tests generating an anime media list entry object
     :return: None
     """
     data = self.generate_sample_anime_entry()
     self.assertEqual(data.id, Id({IdType.MYANIMELIST: 1}))
     self.assertEqual(data.title, Title({TitleType.ROMAJI: "Test"}))
     self.assertEqual(data.relations, [
         Relation(Id({IdType.MYANIMELIST: 1}), MediaType.ANIME,
                  Id({IdType.MYANIMELIST: 2}), MediaType.MANGA,
                  RelationType.SEQUEL)
     ])
     self.assertEqual(data.releasing_status, ReleasingStatus.FINISHED)
     self.assertEqual(data.releasing_start, Date(2018, 1, 1))
     self.assertEqual(data.releasing_end, Date(2018, 4, 4))
     self.assertEqual(data.episode_count, 12)
     self.assertEqual(data.episode_duration, 25)
     self.assertEqual(data.cover_url, "https://example.com/image.png")
     self.assertEqual(data.username, "namboy94")
     self.assertEqual(data.score, Score(55, ScoreType.PERCENTAGE))
     self.assertEqual(data.consuming_status, ConsumingStatus.COMPLETED)
     self.assertEqual(data.episode_progress, 12)
     self.assertEqual(data.consuming_start, Date(2018, 1, 1))
     self.assertEqual(data.consuming_end, Date(2018, 4, 4))
     self.assertEqual(data.media_type, MediaType.ANIME)
    def test_using_same_ids(self):
        """
        Makes sure that using the same ID for both the source and the
        destination results in an error
        :return: None
        """
        source = Id({IdType.MYANIMELIST: 1})
        try:
            Relation(source, MediaType.ANIME, source, MediaType.ANIME,
                     RelationType.OTHER)
            self.fail()
        except ValueError:
            pass

        Relation(source, MediaType.ANIME, source, MediaType.MANGA,
                 RelationType.OTHER)
 def test_invalid_constructor_parameters(self):
     """
     Tests using invalid parameter types with the constructor
     :return: None
     """
     source = Id({IdType.MYANIMELIST: 1})
     dest = Id({IdType.MYANIMELIST: 2})
     for parameters in [
         (None, MediaType.ANIME, dest, MediaType.ANIME,
          RelationType.SEQUEL),
         (source, MediaType.ANIME, None, MediaType.ANIME,
          RelationType.SEQUEL),
         (source, MediaType.ANIME, dest, MediaType.ANIME, None),
         (1, MediaType.ANIME, 2, MediaType.ANIME, RelationType.SEQUEL),
         (True, MediaType.ANIME, False, MediaType.ANIME,
          RelationType.SEQUEL),
         (source, MediaType.ANIME, dest, MediaType.ANIME, "SEQUEL"),
         (source, "ANIME", dest, MediaType.ANIME, RelationType.SEQUEL),
         (source, MediaType.ANIME, dest, "MANGA", RelationType.SEQUEL)
     ]:
         try:
             Relation(*parameters)
             self.fail()
         except TypeError:
             pass
 def test_deserialization(self):
     """
     Tests deserializing an ID object
     :return: None
     """
     source = Id({IdType.MYANIMELIST: 1})
     dest = Id({IdType.MYANIMELIST: 2})
     data = {
         "source": source.serialize(),
         "source_type": "ANIME",
         "dest": dest.serialize(),
         "dest_type": "MANGA",
         "type": "SEQUEL"
     }
     self.assertEqual(
         Relation.deserialize(data),
         Relation(source, MediaType.ANIME, dest, MediaType.MANGA,
                  RelationType.SEQUEL))
    def test_serialization(self):
        """
        Tests serializing a Relation object
        :return: None
        """
        source = Id({IdType.MYANIMELIST: 1})
        dest = Id({IdType.MYANIMELIST: 2})
        ob = Relation(source, MediaType.ANIME, dest, MediaType.MANGA,
                      RelationType.SEQUEL)
        data = ob.serialize()

        self.assertEqual(
            data, {
                "source": source.serialize(),
                "source_type": "ANIME",
                "dest": dest.serialize(),
                "dest_type": "MANGA",
                "type": "SEQUEL"
            })
 def generate_sample_manga_data() -> MangaData:
     """
     Generates a generic MangaData object
     :return: The generated manga data object
     """
     return MangaData(Id(
         {IdType.MYANIMELIST: 1}), Title({TitleType.ROMAJI: "Test"}), [
             Relation(Id({IdType.MYANIMELIST: 1}), MediaType.MANGA,
                      Id({IdType.MYANIMELIST: 2}), MediaType.MANGA,
                      RelationType.SEQUEL)
         ], ReleasingStatus.FINISHED, Date(2018, 1, 1), Date(2018, 4, 4),
                      "https://example.com/image.png", 100, 10)
 def test_generating_manga_data(self):
     """
     Tests generating a manga data object
     :return: None
     """
     data = self.generate_sample_manga_data()
     self.assertEqual(data.id, Id({IdType.MYANIMELIST: 1}))
     self.assertEqual(data.title, Title({TitleType.ROMAJI: "Test"}))
     self.assertEqual(data.relations, [
         Relation(Id({IdType.MYANIMELIST: 1}), MediaType.MANGA,
                  Id({IdType.MYANIMELIST: 2}), MediaType.MANGA,
                  RelationType.SEQUEL)
     ])
     self.assertEqual(data.releasing_status, ReleasingStatus.FINISHED)
     self.assertEqual(data.releasing_start, Date(2018, 1, 1))
     self.assertEqual(data.releasing_end, Date(2018, 4, 4))
     self.assertEqual(data.chapter_count, 100)
     self.assertEqual(data.volume_count, 10)
     self.assertEqual(data.cover_url, "https://example.com/image.png")
     self.assertEqual(data.media_type, MediaType.MANGA)
 def generate_sample_serialized_anime_data() -> \
         Dict[str, Optional[str or int or float or bool
              or Dict or List or Tuple or Set]]:
     """
     Generates some sample serialized anime data
     :return: The serialized sample data
     """
     return {
         "media_type":
         "ANIME",
         "id":
         Id({
             IdType.MYANIMELIST: 1
         }).serialize(),
         "title":
         Title({
             TitleType.ROMAJI: "Test"
         }).serialize(),
         "relations": [
             Relation(Id({IdType.MYANIMELIST: 1}), MediaType.ANIME,
                      Id({IdType.MYANIMELIST: 2}), MediaType.MANGA,
                      RelationType.SEQUEL).serialize()
         ],
         "releasing_status":
         ReleasingStatus.FINISHED.name,
         "releasing_start":
         Date(2018, 1, 1).serialize(),
         "releasing_end":
         Date(2018, 4, 4).serialize(),
         "episode_count":
         12,
         "episode_duration":
         25,
         "cover_url":
         "https://example.com/image.png"
     }
 def test_important_relations(self):
     """
     Tests if relations are correctly identified as "important"
     :return: None
     """
     source = Id({IdType.MYANIMELIST: 1})
     dest = Id({IdType.MYANIMELIST: 2})
     for relation_type, important in {
             RelationType.SEQUEL: True,
             RelationType.PREQUEL: True,
             RelationType.PARENT: True,
             RelationType.SIDE_STORY: True,
             RelationType.SUMMARY: True,
             RelationType.SPIN_OFF: False,
             RelationType.CHARACTER: False,
             RelationType.ADAPTATION: False,
             RelationType.OTHER: False
     }.items():
         same_type_relation = Relation(source, MediaType.ANIME, dest,
                                       MediaType.ANIME, relation_type)
         self.assertEqual(same_type_relation.is_important(), important)
         other_type_relation = Relation(source, MediaType.ANIME, dest,
                                        MediaType.MANGA, relation_type)
         self.assertFalse(other_type_relation.is_important())
    def __generate_media_data(media_type: MediaType,
                              data: Dict[str, Any]) -> MediaData:
        """
        Generates an MediaData object from a GraphQL result
        :param media_type: The media type to generate
        :param data: The data to convert into an AnimeData object
        :return: The generated AnimeData object
        """
        _id = Id({
            IdType.ANILIST: data["id"],
            IdType.MYANIMELIST: data["idMal"]
        })

        title = Title({
            TitleType.ROMAJI: data["title"]["romaji"],
            TitleType.ENGLISH: data["title"]["english"],
            TitleType.JAPANESE: data["title"]["native"],
        })
        if title.get(TitleType.ENGLISH) is None:
            title.set(title.get(TitleType.ROMAJI), TitleType.ENGLISH)

        relations = []
        for relation in data["relations"]["edges"]:
            dest_id = Id({
                IdType.ANILIST: relation["node"]["id"],
                IdType.MYANIMELIST: relation["node"]["idMal"]
            })
            dest_media_type = media_type
            rel_type = RelationType[relation["relationType"]]

            if rel_type == RelationType.ADAPTATION:
                if media_type == MediaType.ANIME:
                    dest_media_type = MediaType.MANGA
                else:
                    dest_media_type = MediaType.ANIME

            relations.append(
                Relation(_id, media_type, dest_id, dest_media_type,
                         rel_type).serialize())

        releasing_status = \
            data["status"].replace("NOT_YET_RELEASED", "NOT_RELEASED")

        serialized = {
            "media_type": media_type.name,
            "id": _id.serialize(),
            "title": title.serialize(),
            "relations": relations,
            "releasing_status": releasing_status,
            "cover_url": data["coverImage"]["large"],
            "episode_count": data["episodes"],
            "episode_duration": data["duration"],
            "chapter_count": data["episodes"],
            "volume_count": data["episodes"]
        }

        for api_key, dict_key in {
                "startDate": "releasing_start",
                "endDate": "releasing_end"
        }.items():
            try:
                serialized[dict_key] = Date(data[api_key]["year"],
                                            data[api_key]["month"],
                                            data[api_key]["day"]).serialize()
            except (TypeError, ValueError):
                serialized[dict_key] = None

        return MediaData.deserialize(serialized)
 def test_invalid_deserialization(self):
     """
     Tests that invalid serialized data raises ValueErrors when deserialized
     :return: None
     """
     source = Id({IdType.MYANIMELIST: 1}).serialize()
     dest = Id({IdType.MYANIMELIST: 2}).serialize()
     for data in [{
             "source": source,
             "dest": dest,
             "type": "Sequel",
             "source_type": "ANIME",
             "dest_type": "MANGA"
     }, {
             "source": source,
             "dest": None,
             "type": "SEQUEL",
             "source_type": "ANIME",
             "dest_type": "MANGA"
     }, {
             "source": None,
             "dest": dest,
             "type": "SEQUEL",
             "source_type": "ANIME",
             "dest_type": "MANGA"
     }, {
             "source": source,
             "dest": dest,
             "source_type": "ANIME",
             "dest_type": "MANGA"
     }, {
             "source": source,
             "type": "SEQUEL",
             "source_type": "ANIME",
             "dest_type": "MANGA"
     }, {
             "dest": dest,
             "type": "SEQUEL",
             "source_type": "ANIME",
             "dest_type": "MANGA"
     }, {
             "source": 1,
             "dest": dest,
             "type": "Sequel",
             "source_type": "ANIME",
             "dest_type": "MANGA"
     }, {
             "source": source,
             "dest": 2,
             "type": "Sequel",
             "source_type": "ANIME",
             "dest_type": "MANGA"
     }, {
             "source": source,
             "dest": dest,
             "type": "Sequel"
     }, []]:
         try:
             Relation.deserialize(data)
             self.fail()
         except (ValueError, TypeError):
             pass