Coverage for src/qdrant_loader/connectors/jira/models.py: 100%

47 statements  

« prev     ^ index     » next       coverage.py v7.15.0, created at 2026-07-20 10:15 +0000

1"""Data models for Jira connector.""" 

2 

3from datetime import datetime 

4from typing import Literal 

5 

6from pydantic import BaseModel, ConfigDict, Field, HttpUrl 

7 

8 

9class JiraUser(BaseModel): 

10 """Jira user model.""" 

11 

12 account_id: str = Field(..., description="User's account ID") 

13 display_name: str = Field(..., description="User's display name") 

14 email_address: str | None = Field(None, description="User's email address") 

15 

16 

17class JiraComment(BaseModel): 

18 """Jira comment model.""" 

19 

20 id: str = Field(..., description="Comment ID") 

21 body: str = Field(..., description="Comment content") 

22 created: datetime = Field(..., description="Comment creation timestamp") 

23 updated: datetime | None = Field(None, description="Comment last update timestamp") 

24 author: JiraUser = Field(..., description="User who created the comment") 

25 

26 

27class JiraAttachment(BaseModel): 

28 """Jira attachment model.""" 

29 

30 id: str = Field(..., description="Attachment ID") 

31 filename: str = Field(..., description="Attachment filename") 

32 size: int = Field(..., description="Attachment size in bytes") 

33 mime_type: str = Field(..., description="Attachment MIME type") 

34 content_url: HttpUrl = Field(..., description="URL to download attachment content") 

35 created: datetime = Field(..., description="Attachment creation timestamp") 

36 author: JiraUser = Field(..., description="User who attached the file") 

37 

38 

39class JiraIssueLink(BaseModel): 

40 """A single Jira issue link, preserving direction and relationship type.""" 

41 

42 key: str = Field(..., description="Key of the linked issue") 

43 link_type: str | None = Field( 

44 None, description="Jira link type name (e.g. 'Blocks', 'Cloners')" 

45 ) 

46 direction: Literal["inward", "outward"] = Field( 

47 ..., 

48 description="Direction of the link relative to this issue: 'inward' or 'outward'", 

49 ) 

50 relation: str | None = Field( 

51 None, 

52 description=( 

53 "Human-readable relationship phrase from this issue's perspective " 

54 "(e.g. 'blocks', 'is cloned by')" 

55 ), 

56 ) 

57 

58 

59class JiraIssue(BaseModel): 

60 """Jira issue model.""" 

61 

62 model_config = ConfigDict(extra="allow") 

63 id: str = Field(..., description="Issue ID") 

64 key: str = Field(..., description="Issue key") 

65 summary: str = Field(..., description="Issue summary") 

66 description: str | None = Field(None, description="Issue description") 

67 issue_type: str = Field(..., description="Issue type") 

68 status: str = Field(..., description="Issue status") 

69 priority: str | None = Field(None, description="Issue priority") 

70 project_key: str = Field(..., description="Project key") 

71 created: datetime = Field(..., description="Issue creation timestamp") 

72 updated: datetime = Field(..., description="Last update timestamp") 

73 reporter: JiraUser = Field(..., description="Issue reporter") 

74 assignee: JiraUser | None = Field(None, description="Issue assignee") 

75 labels: list[str] = Field(default_factory=list, description="Issue labels") 

76 attachments: list[JiraAttachment] = Field( 

77 default_factory=list, description="Issue attachments" 

78 ) 

79 comments: list[JiraComment] = Field( 

80 default_factory=list, description="Issue comments" 

81 ) 

82 parent_key: str | None = Field(None, description="Parent issue key for subtasks") 

83 subtasks: list[str] = Field( 

84 default_factory=list, description="List of subtask keys" 

85 ) 

86 linked_issues: list[str] = Field( 

87 default_factory=list, description="List of linked issue keys" 

88 ) 

89 linked_issue_details: list[JiraIssueLink] = Field( 

90 default_factory=list, 

91 description="Linked issues with relationship type and direction", 

92 )