Coverage for otaku_info/external/entities/MyanimelistItem.py: 85%
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""LICENSE
2Copyright 2020 Hermann Krumrey <hermann@krumreyh.com>
4This file is part of otaku-info.
6otaku-info is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
11otaku-info is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
16You should have received a copy of the GNU General Public License
17along with otaku-info. If not, see <http://www.gnu.org/licenses/>.
18LICENSE"""
19import logging
20from typing import Dict, Any
21from otaku_info.enums import MediaType, MediaSubType, \
22 ReleasingState, ListService, MediaRelationType
23from otaku_info.external.entities.AnimeListItem import AnimeListItem
26class MyanimelistItem(AnimeListItem):
27 """
28 Class that models a general myanimelist list item
29 Represents the information fetched using myanimelist's jikan API
30 """
32 @classmethod
33 def from_query(cls, media_type: MediaType, data: Dict[str, Any]) \
34 -> "MyanimelistItem":
35 """
36 Generates an MyanimelistItem from a dictionary generated
37 by an APi query
38 :param media_type: The media type of the item
39 :param data: The data to use
40 :return: The generated MyanimelistItem
41 """
42 media_subtype = cls.resolve_media_subtype(data["type"])
43 releasing_state = cls.resolve_releasing_state(data["status"])
45 relations = {}
46 for edge_type, edges in data["related"].items():
47 relation_type = cls.resolve_relation_type(edge_type)
48 for edge in edges:
49 node_type = MediaType(edge["type"])
50 node_id = edge["mal_id"]
51 relations[(node_type, node_id)] = relation_type
53 return cls(
54 data["mal_id"],
55 ListService.MYANIMELIST,
56 {},
57 media_type,
58 media_subtype,
59 data["title_english"],
60 data["title"],
61 data["image_url"],
62 data.get("chapters"),
63 data.get("volumes"),
64 data.get("episodes"),
65 None,
66 None,
67 releasing_state,
68 relations
69 )
71 @staticmethod
72 def resolve_relation_type(relation_string: str) -> MediaRelationType:
73 """
74 Resolves myanimelist relation types
75 :param relation_string: The string to resolve
76 :return: The resolved MediaRelationType
77 """
78 base = {
79 x.value.lower().replace("_", " "): x
80 for x in MediaRelationType
81 }
82 base.update({
83 "parent story": MediaRelationType.PARENT,
84 "alternative setting": MediaRelationType.ALTERNATIVE,
85 "alternative version": MediaRelationType.ALTERNATIVE,
86 "spin-off": MediaRelationType.SPIN_OFF
87 })
88 relation = base.get(relation_string.lower())
89 if relation is None: 89 ↛ 90line 89 didn't jump to line 90, because the condition on line 89 was never true
90 logging.error(
91 f"Missing MAL mapping: 'relation_type:{relation_string}'"
92 )
93 return MediaRelationType.OTHER
94 else:
95 return relation
97 @staticmethod
98 def resolve_releasing_state(releasing_string: str) -> ReleasingState:
99 """
100 Resolves myanimelist releasing state
101 :param releasing_string: The string to resolve
102 :return: The resolved ReleasingState
103 """
104 base = {
105 x.value.lower().replace("_", " "): x
106 for x in ReleasingState
107 }
108 base.update({
109 "finished airing": ReleasingState.FINISHED,
110 "publishing": ReleasingState.RELEASING,
111 "airing": ReleasingState.RELEASING,
112 "discontinued": ReleasingState.CANCELLED,
113 "on hiatus": ReleasingState.UNKNOWN
114 })
115 state = base.get(releasing_string.lower())
116 if state is None: 116 ↛ 117line 116 didn't jump to line 117, because the condition on line 116 was never true
117 logging.error(
118 f"Missing MAL mapping: 'releasing_state:{releasing_string}'"
119 )
120 return ReleasingState.UNKNOWN
121 else:
122 return state
124 @staticmethod
125 def resolve_media_subtype(subtype_string: str) -> MediaSubType:
126 """
127 Resolves myanimelist media subtype
128 :param subtype_string: The string to resolve
129 :return: The resolved MediaSubType
130 """
131 base = {
132 x.value.lower().replace("_", " "): x
133 for x in MediaSubType
134 }
135 base.update({
136 "one-shot": MediaSubType.ONE_SHOT,
137 "light novel": MediaSubType.NOVEL
138 })
139 subtype = base.get(subtype_string.lower())
140 if subtype is None: 140 ↛ 141line 140 didn't jump to line 141, because the condition on line 140 was never true
141 logging.error(
142 f"Missing MAL mapping: subtype:'{subtype_string}'"
143 )
144 return MediaSubType.UNKNOWN
145 else:
146 return subtype