Hot-keys 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 2015 Hermann Krumrey <hermann@krumreyh.com>
4This file is part of toktokkie.
6toktokkie 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.
11toktokkie 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 toktokkie. If not, see <http://www.gnu.org/licenses/>.
18LICENSE"""
20import os
21import json
22import logging
23from abc import ABC
24from typing import Optional, Any, Dict, List
25from toktokkie.enums import MediaType, IdType
26from toktokkie.metadata.base.IdHelper import IdHelper
29class MetadataBase(IdHelper, ABC):
30 """
31 Base class for all metadata classes. Specifies most of the
32 methods required by Metadata classes.
33 """
35 logger = logging.getLogger(__name__)
36 """
37 Logger for the metadata class
38 """
40 directory_path: str
41 """
42 The path to the directory this metadata describes
43 """
45 json: Dict[str, Any]
47 @property
48 def metadata_file(self) -> str:
49 """
50 :return: The path to the metadata file
51 """
52 return os.path.join(self.directory_path, ".meta/info.json")
54 @property
55 def icon_directory(self) -> str:
56 """
57 :return: The path to the the icon directory
58 """
59 return os.path.join(self.directory_path, ".meta/icons")
61 @property
62 def name(self) -> str:
63 """
64 :return: The name of the media
65 """
66 return os.path.basename(os.path.abspath(self.directory_path))
68 @name.setter
69 def name(self, name: str):
70 """
71 Renames the media directory
72 :param name: The new name of the media directory
73 :return: None
74 """
75 new_path = os.path.join(os.path.dirname(self.directory_path), name)
76 os.rename(self.directory_path, new_path)
77 self.directory_path = new_path
79 @property
80 def tags(self) -> List[str]:
81 """
82 :return: A list of tags
83 """
84 return self.json.get("tags", [])
86 @tags.setter
87 def tags(self, tags: List[str]):
88 """
89 Setter method for the tags property
90 :param tags: The tags to set
91 :return: None
92 """
93 self.json["tags"] = tags
95 @property
96 def ids(self) -> Dict[IdType, List[str]]:
97 """
98 :return: A dictionary containing lists of IDs mapped to ID types
99 """
100 return self.fill_ids(
101 self.objectify_ids(self.json["ids"]),
102 self.valid_id_types()
103 )
105 @ids.setter
106 def ids(self, ids: Dict[IdType, List[str]]):
107 """
108 Setter method for the IDs of the metadata object.
109 Previous IDs will be overwritten!
110 :param ids: The IDs to set
111 :return: None
112 """
113 self.json["ids"] = self.stringify_ids(self.minimize_ids(ids))
115 @property
116 def urls(self) -> Dict[IdType, List[str]]:
117 """
118 Generates URLs for the stored ID types of this metadata object
119 :return: The URLs mapped to their respective id types
120 """
121 ids = self.ids
122 urls: Dict[IdType, List[str]] = {x: [] for x in ids.keys()}
124 for id_type, values in ids.items():
125 for value in values:
126 url = self.generate_url_for_id(
127 id_type,
128 self.media_type(),
129 value
130 )
131 urls[id_type].append(url)
133 return urls
135 @classmethod
136 def media_type(cls) -> MediaType:
137 """
138 :return: The media type of the Metadata class
139 """
140 raise NotImplementedError() # pragma: no cover
142 @classmethod
143 def valid_id_types(cls) -> List[IdType]:
144 """
145 :return: Valid ID types for the metadata
146 """
147 raise NotImplementedError() # pragma: no cover
149 @classmethod
150 def required_id_types(cls) -> List[IdType]:
151 """
152 :return: Required ID types for the metadata
153 """
154 return [] # pragma: no cover
156 def __str__(self) -> str:
157 """
158 :return: A string representation of the metadata
159 """
160 json_data = json.dumps(
161 self.json,
162 sort_keys=True,
163 indent=4,
164 separators=(",", ": ")
165 )
166 return "Name: {}\nMedia Type: {}\nInfo:\n{}".format(
167 self.name,
168 self.media_type().name,
169 json_data
170 )
172 def __eq__(self, other: object) -> bool:
173 """
174 Checks equality with another object
175 :param other: The other object
176 :return: True if equal, False otherwise
177 """
178 if not isinstance(other, type(self)):
179 return False
180 else:
181 return self.json == other.json
183 def write(self):
184 """
185 Writes the metadata to the metadata file
186 :return: None
187 """
188 self.logger.debug("Writing Metadata: {}".format(self.json))
190 if not os.path.isdir(os.path.dirname(self.metadata_file)):
191 os.makedirs(os.path.dirname(self.metadata_file))
193 self.json["type"] = self.media_type().value
195 with open(self.metadata_file, "w") as f:
196 f.write(json.dumps(
197 self.json,
198 sort_keys=True,
199 indent=4,
200 separators=(",", ": ")
201 ))
203 def print_folder_icon_source(self):
204 """
205 Prints a message with a URL for possible folder icons on deviantart
206 :return: None
207 """
208 deviantart = "https://www.deviantart.com"
209 url = "{}/popular-all-time/?section=&global=1&q={}".format(
210 deviantart,
211 "+".join(self.name.split(" ") + ["folder", "icon"])
212 )
213 print("Search folder icons here:")
214 print(url)
216 def set_ids(self, id_type: IdType, ids: List[str]):
217 """
218 Sets IDs for one ID type to the metadata
219 :param id_type: The id type
220 :param ids: The IDs to set
221 :return: None
222 """
223 metadata_ids = self.ids
224 metadata_ids[id_type] = ids
225 self.ids = metadata_ids
227 def get_icon_file(self, name: str) -> Optional[str]:
228 """
229 Retrieves the path to an icon file, if it exists
230 :param name: The name of the icon.
231 :return: The path to the icon file or None, if the file does not exist
232 """
233 path = os.path.join(self.icon_directory, "{}.png".format(name))
234 if os.path.isfile(path):
235 return path
236 else:
237 return None