Coverage for /usr/lib/python3.10/site-packages/hyd/backend/tag/models.py: 100%

35 statements  

« prev     ^ index     » next       coverage.py v7.0.3, created at 2023-01-05 16:38 +0000

1import datetime as dt 

2from typing import TypedDict 

3 

4from fastapi import status 

5from sqlalchemy import ( 

6 Boolean, 

7 Column, 

8 ForeignKey, 

9 ForeignKeyConstraint, 

10 Integer, 

11 String, 

12) 

13from sqlalchemy.orm import Mapped, relationship 

14 

15from hyd.backend.db import EXTEND_EXISTING, DeclarativeMeta 

16from hyd.backend.project.models import ProjectEntry 

17from hyd.backend.util.const import MAX_LENGTH_STR_ID 

18from hyd.backend.util.models import ( 

19 BASE_API_RESPONSE_SCHEMA, 

20 DETAIL_STR, 

21 NameStr, 

22 PrimaryKey, 

23 TimeStampMixin, 

24) 

25from hyd.backend.version.models import VersionEntry 

26 

27#################################################################################################### 

28#### SQLAlchemy table definitions 

29#################################################################################################### 

30 

31 

32class TagEntry(DeclarativeMeta, TimeStampMixin): 

33 __tablename__ = "tag_table" 

34 __table_args__ = ( 

35 ForeignKeyConstraint( 

36 ["project_id", "version"], [VersionEntry.project_id, VersionEntry.version] 

37 ), 

38 {"extend_existing": EXTEND_EXISTING}, 

39 ) 

40 project_id: Mapped[PrimaryKey] = Column(Integer, ForeignKey(ProjectEntry.id), primary_key=True) 

41 version: Mapped[NameStr | None] = Column( 

42 String(length=MAX_LENGTH_STR_ID), nullable=True, default=None 

43 ) 

44 

45 tag: Mapped[NameStr] = Column(String(length=MAX_LENGTH_STR_ID), primary_key=True) 

46 primary: Mapped[bool] = Column(Boolean) # primary == False will be marked as copy for google 

47 

48 project_entry: Mapped[ProjectEntry] = relationship( 

49 ProjectEntry, back_populates="tag_entries", viewonly=True 

50 ) 

51 version_entry: Mapped[VersionEntry] = relationship( 

52 VersionEntry, back_populates="tag_entries", viewonly=True 

53 ) 

54 # no cascade="delete" because delete has to be done manually to remove files from disc 

55 

56 

57class PrimaryTagEntry(DeclarativeMeta, TimeStampMixin): 

58 __tablename__ = "primary_tag_table" 

59 __table_args__ = ( 

60 ForeignKeyConstraint(["project_id", "primary_tag"], [TagEntry.project_id, TagEntry.tag]), 

61 {"extend_existing": EXTEND_EXISTING}, 

62 ) 

63 

64 project_id: Mapped[PrimaryKey] = Column(Integer, primary_key=True) 

65 primary_tag: Mapped[NameStr] = Column(String(length=MAX_LENGTH_STR_ID)) 

66 

67 

68#################################################################################################### 

69#### Response schema 

70#################################################################################################### 

71 

72 

73class TagResponseSchema(TypedDict): 

74 project_id: PrimaryKey 

75 tag: NameStr 

76 created_at: dt.datetime 

77 updated_at: dt.datetime | None 

78 version: NameStr | None 

79 primary: bool 

80 

81 

82#################################################################################################### 

83#### OpenAPI definitions 

84#################################################################################################### 

85 

86 

87API_V1_CREATE__POST = { 

88 **BASE_API_RESPONSE_SCHEMA, 

89 status.HTTP_200_OK: {"model": TagResponseSchema}, 

90 status.HTTP_400_BAD_REQUEST: DETAIL_STR, 

91} 

92 

93 

94API_V1_LIST__GET = { 

95 **BASE_API_RESPONSE_SCHEMA, 

96 status.HTTP_200_OK: {"model": list[TagResponseSchema]}, 

97} 

98 

99 

100API_V1_MOVE__PATCH = { 

101 **BASE_API_RESPONSE_SCHEMA, 

102 status.HTTP_200_OK: {"model": TagResponseSchema}, 

103 status.HTTP_400_BAD_REQUEST: DETAIL_STR, 

104} 

105 

106 

107API_V1_DELETE__DELETE = { 

108 **BASE_API_RESPONSE_SCHEMA, 

109 status.HTTP_200_OK: {"model": TagResponseSchema}, 

110 status.HTTP_400_BAD_REQUEST: DETAIL_STR, 

111}