Coverage for otaku_info/db/LnRelease.py: 52%
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"""
20import re
21from datetime import datetime
22from typing import Optional
23from jerrycan.base import db
24from jerrycan.db.ModelMixin import ModelMixin
25from otaku_info.db.MediaItem import MediaItem
26from otaku_info.enums import MediaType, ListService
29class LnRelease(ModelMixin, db.Model):
30 """
31 Database model that keeps track of light novel releases
32 """
34 def __init__(self, *args, **kwargs):
35 """
36 Initializes the Model
37 :param args: The constructor arguments
38 :param kwargs: The constructor keyword arguments
39 """
40 super().__init__(*args, **kwargs)
42 __tablename__ = "ln_releases"
43 __table_args__ = (db.ForeignKeyConstraint(
44 ("service", "service_id", "media_type"),
45 (MediaItem.service, MediaItem.service_id, MediaItem.media_type)
46 ),)
48 series_name: str = db.Column(db.String(255), primary_key=True)
49 volume: str = db.Column(db.String(255), primary_key=True)
50 digital: bool = db.Column(db.Boolean, primary_key=True)
51 physical: bool = db.Column(db.Boolean, primary_key=True)
53 release_date_string: str = db.Column(db.String(10), nullable=False)
54 publisher: Optional[str] = db.Column(db.String(255), nullable=True)
55 purchase_link: Optional[str] = db.Column(db.String(255), nullable=True)
57 service: Optional[ListService] = \
58 db.Column(db.Enum(ListService), nullable=True)
59 service_id: Optional[str] = db.Column(db.String(255), nullable=True)
60 media_type: Optional[MediaType] = \
61 db.Column(db.Enum(MediaType), nullable=True)
63 media_item: Optional[MediaItem] = db.relationship(
64 "MediaItem", back_populates="ln_releases"
65 )
67 @property
68 def release_date(self) -> datetime:
69 """
70 :return: The release date as a datetime object
71 """
72 return datetime.strptime(self.release_date_string, "%Y-%m-%d")
74 @property
75 def volume_number(self) -> int:
76 """
77 :return: The volume number as an integer
78 """
79 try:
80 if re.match(r"^p[0-9]+[ ]*v[0-9]+$", self.volume.lower()):
81 return int(self.volume.lower().split("v")[1])
82 else:
83 stripped = ""
84 for char in self.volume:
85 if char.isdigit() or char in [".", "-"]:
86 stripped += char
87 if "-" in stripped:
88 stripped = stripped.split("-")[1]
89 if "." in stripped:
90 stripped = stripped.split(".")[0]
91 return int(stripped)
93 except (TypeError, ValueError):
94 return 0