Coverage for bc/kwai-bc-teams/src/kwai_bc_teams/domain/team.py: 89%

45 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2024-01-01 00:00 +0000

1"""Module for defining the team entity.""" 

2 

3from dataclasses import dataclass, field, replace 

4from typing import ClassVar, ItemsView, Iterator, Mapping, Self, Type 

5 

6from kwai_core.domain.entity import DataclassEntity 

7from kwai_core.domain.value_objects.identifier import IntIdentifier 

8from kwai_core.domain.value_objects.unique_id import UniqueId 

9 

10from kwai_bc_teams.domain.team_member import TeamMember 

11 

12 

13class TeamIdentifier(IntIdentifier): 

14 """Identifier for a team.""" 

15 

16 

17class TeamMemberAlreadyExistException(Exception): 

18 """Raised when the member is already part of the team.""" 

19 

20 

21class TeamMembers(Mapping[UniqueId, TeamMember]): 

22 """A immutable dictionary with members of a team.""" 

23 

24 def __init__(self, members: Mapping[UniqueId, TeamMember] | None = None): 

25 self._members = {} if members is None else dict(members) 

26 

27 def add(self, team_member: TeamMember) -> Self: 

28 """Add a new team member. 

29 

30 This class is immutable, so this method will return a new instance. 

31 """ 

32 return type(self)(self._members | {team_member.member.uuid: team_member}) 

33 

34 def remove(self, team_member: TeamMember) -> Self: 

35 """Remove a team member. 

36 

37 This class is immutable, so this method will return a new instance. 

38 """ 

39 result = type(self)(self._members) 

40 del result._members[team_member.member.uuid] 

41 return result 

42 

43 def items(self) -> ItemsView[UniqueId, TeamMember]: 

44 """Return the items of the team members.""" 

45 return self._members.items() 

46 

47 def __contains__(self, key): 

48 """Check if the key is in the dictionary.""" 

49 return key in self._members 

50 

51 def __getitem__(self, key: UniqueId): 

52 """Return the item with the given key.""" 

53 return self._members.get(key) 

54 

55 def __iter__(self) -> Iterator[UniqueId]: 

56 """Create an iterator.""" 

57 return iter(self._members) 

58 

59 def __len__(self) -> int: 

60 """Return the number of items.""" 

61 return len(self._members) 

62 

63 def __hash__(self): 

64 """Create a hash.""" 

65 return hash(self._members.items()) 

66 

67 

68@dataclass(kw_only=True, eq=False, slots=True, frozen=True) 

69class TeamEntity(DataclassEntity): 

70 """Entity for a team of the club. 

71 

72 Attributes: 

73 name: The name of the team. 

74 active: Is this team active? 

75 remark: A remark about this team. 

76 members: Members of this team. 

77 """ 

78 

79 ID: ClassVar[Type] = TeamIdentifier 

80 

81 name: str 

82 active: bool = True 

83 remark: str = "" 

84 members: TeamMembers = field(default_factory=TeamMembers) 

85 

86 def __str__(self): 

87 """Return string representation of the team entity.""" 

88 return f"<Team id={self.id} name={self.name}>" 

89 

90 def __repr__(self): 

91 """Return representation of the team entity.""" 

92 return f"<{self.__class__.__name__} id={self.id} name={self.name!r}>" 

93 

94 def add_member(self, team_member: TeamMember) -> Self: 

95 """Add a member to the team.""" 

96 if team_member.member.uuid in self.members: 

97 raise TeamMemberAlreadyExistException( 

98 f"Team member (id={team_member.member.id}) already part of team {self.name}" 

99 ) 

100 return replace( 

101 self, 

102 members=self.members.add(team_member), 

103 ) 

104 

105 def remove_member(self, team_member: TeamMember) -> Self: 

106 """Remove a team member.""" 

107 return replace(self, members=self.members.remove(team_member))