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

42 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""" 

19 

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 

27 

28 

29class LnRelease(ModelMixin, db.Model): 

30 """ 

31 Database model that keeps track of light novel releases 

32 """ 

33 

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) 

41 

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 ),) 

47 

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) 

52 

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) 

56 

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) 

62 

63 media_item: Optional[MediaItem] = db.relationship( 

64 "MediaItem", back_populates="ln_releases" 

65 ) 

66 

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

73 

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) 

92 

93 except (TypeError, ValueError): 

94 return 0