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

44 statements  

1"""LICENSE 

2Copyright 2020 Hermann Krumrey <hermann@krumreyh.com> 

3 

4This file is part of otaku-info. 

5 

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. 

10 

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. 

15 

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 

24 

25 

26class MyanimelistItem(AnimeListItem): 

27 """ 

28 Class that models a general myanimelist list item 

29 Represents the information fetched using myanimelist's jikan API 

30 """ 

31 

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"]) 

44 

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 

52 

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 ) 

70 

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 

96 

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 

123 

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