Coverage for src/lanraragi_api/entity/archive.py: 61%

41 statements  

« prev     ^ index     » next       coverage.py v7.16.0, created at 2026-09-22 23:20 +0000

1from typing import Any 

2 

3from pydantic import BaseModel, Field 

4 

5ARCHIVE_TAG_VALUES_SET = "ONLY_VALUES" 

6 

7 

8class ArchiveMetadata(BaseModel): 

9 """Metadata of a single Archive. 

10 

11 Attributes: 

12 arcid: Unique identifier for the archive, a 40 character SHA1 hash. 

13 extension: File extension of the archive. 

14 filename: Filename of the archive. 

15 isnew: Whether the archive is newly added. Defaults to None. 

16 lastreadtime: Unix timestamp of when the archive was last read. 

17 pagecount: Total number of pages in the archive. 

18 progress: Reading progress, as a page number. 

19 size: Size of the archive in bytes. 

20 summary: Summary description of the archive. Defaults to None. 

21 toc: Table of contents for the archive, as objects holding the ``page`` 

22 where a chapter starts and its ``name``. Defaults to None. 

23 tags: Comma-separated list of tags associated with the archive, with 

24 namespaced tags in ``namespace:value`` form. 

25 title: Title of the archive. 

26 """ 

27 

28 arcid: str = Field(...) 

29 extension: str = Field(...) 

30 filename: str = Field(...) 

31 isnew: bool | str | None = Field(default=None) 

32 lastreadtime: int = Field(...) 

33 pagecount: int = Field(...) 

34 progress: int = Field(...) 

35 size: int = Field(...) 

36 summary: str | None = Field(default=None) 

37 toc: list[dict[Any, Any]] | None = Field(default=None) 

38 

39 # k1:v1, k2:v21, k2:v22, v3, v4 

40 # allow duplicate keys, only values 

41 tags: str = Field(...) 

42 title: str = Field(...) 

43 

44 

45class ArchiveTags: 

46 """Offer utility methods to operate ``ArchiveMetadata.tags``""" 

47 

48 def __init__(self, tags: str): 

49 self._tags: str = tags 

50 

51 @property 

52 def tags(self): 

53 """Get the ``tags`` string represented by this class""" 

54 return self._tags 

55 

56 def get_tag_list(self) -> list[str]: 

57 """Get a list of tags""" 

58 tags = [t.strip() for t in self._tags.split(",")] 

59 tags = [t for t in tags if t != ""] 

60 return tags 

61 

62 def set_tag(self, tag_list: list[str]): 

63 """Set the inner ``tags`` by a list of tags. Note that there will be 

64 a deduplication first. 

65 """ 

66 # deduplicate first 

67 tag_list = list(dict.fromkeys(tag_list)) 

68 self._tags = ",".join(tag_list) 

69 

70 def get_artists(self) -> list[str]: 

71 """Get all artists in a list from tags prefixed with ``artist:``.""" 

72 tag_list = self.get_tag_list() 

73 return [t[len("artist:") :] for t in tag_list if t.startswith("artist:")] 

74 

75 def set_artists(self, artists: list[str]): 

76 """Set/Overwrite existing artists. 

77 

78 Consider using ``append_artists`` method if you want to add some new 

79 artists. 

80 

81 """ 

82 tag_list = self.get_tag_list() 

83 tag_list = [t for t in tag_list if not t.startswith("artist:")] 

84 self.set_tag(tag_list) 

85 

86 self.append_artists(artists) 

87 

88 def append_artists(self, artists: list[str]): 

89 """Add some new artists to the existing ones.""" 

90 tag_list = self.get_tag_list() 

91 tag_list += [f"artist:{a}" for a in artists] 

92 self.set_tag(tag_list)