Coverage for functions \ flipdare \ firestore \ context \ group_member_context.py: 45%

77 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-05-08 12:22 +1000

1#!/usr/bin/env python 

2# Copyright (c) 2026 Flipdare Pty Ltd. All rights reserved. 

3# 

4# This file is part of Flipdare's proprietary software and contains 

5# confidential and copyrighted material. Unauthorised copying, 

6# modification, distribution, or use of this file is strictly 

7# prohibited without prior written permission from Flipdare Pty Ltd. 

8# 

9# This software includes third-party components licensed under MIT, 

10# BSD, and Apache 2.0 licences. See THIRD_PARTY_NOTICES for details. 

11# 

12 

13from __future__ import annotations 

14 

15from typing import TYPE_CHECKING, Any, override 

16from flipdare.app_types import DatabaseDict 

17from flipdare.firestore.context._model_context import ModelContext 

18from flipdare.firestore.context._model_context_factory import ModelContextFactory 

19from flipdare.wrapper import ( 

20 GroupMemberWrapper, 

21 GroupWrapper, 

22 UserWrapper, 

23) 

24 

25if TYPE_CHECKING: 

26 from flipdare.manager.db_manager import DbManager 

27 

28__all__ = ["GroupMemberContextFactory", "GroupMemberContext"] 

29 

30 

31class GroupMemberContextFactory(ModelContextFactory[GroupMemberWrapper, "GroupMemberContext"]): 

32 

33 def __init__(self, db_manager: DbManager | None = None) -> None: 

34 super().__init__(db_manager=db_manager) 

35 

36 @override 

37 def create(self, obj: Any) -> GroupMemberContext | None: 

38 if isinstance(obj, GroupMemberContext): 

39 return obj 

40 if isinstance(obj, GroupMemberWrapper): 

41 return self._from_model(obj) 

42 if isinstance(obj, str): 

43 return self._from_id(obj) 

44 obj_data: DatabaseDict = obj # set explicity type for type checkers. 

45 return self._from_data(obj_data) 

46 

47 @override 

48 def _from_id(self, doc_id: str) -> GroupMemberContext | None: 

49 # NOTE: from_id is inherited and does not support sub-collections 

50 raise RuntimeError( 

51 f"GroupMemberContextFactory does not support from_id for doc_id: {doc_id}", 

52 ) 

53 

54 @override 

55 def _from_data(self, data: DatabaseDict) -> GroupMemberContext | None: 

56 try: 

57 # from_dict returns PersistedWrapper[GroupMemberWrapper] 

58 member: GroupMemberWrapper = GroupMemberWrapper.from_dict(data) 

59 return self._from_model(member) 

60 except Exception: 

61 return None 

62 

63 @override 

64 def _from_model( 

65 self, 

66 model: GroupMemberWrapper, 

67 ) -> GroupMemberContext | None: 

68 

69 group = self.get_group(model.gid) # Returns GroupWrapper | None 

70 user = self.get_user(model.uid) # Returns UserWrapper | None 

71 owner: UserWrapper | None = None 

72 if group is not None: 

73 owner = self.get_user(group.model.uid) 

74 

75 return GroupMemberContext(group=group, user=user, owner=owner) 

76 

77 

78class GroupMemberContext(ModelContext): 

79 

80 def __init__( 

81 self, 

82 group: GroupWrapper | None = None, 

83 user: UserWrapper | None = None, 

84 owner: UserWrapper | None = None, 

85 ) -> None: 

86 self._group = group 

87 self._user = user 

88 self._owner = owner 

89 

90 # Call super().__init__() LAST - it calls validate() 

91 super().__init__() 

92 

93 @property 

94 def group(self) -> GroupWrapper: 

95 self._require_valid("access group") 

96 return self._group # type: ignore 

97 

98 @property 

99 def user(self) -> UserWrapper: 

100 self._require_valid("access user") 

101 return self._user # type: ignore 

102 

103 @property 

104 def owner(self) -> UserWrapper: 

105 self._require_valid("access owner") 

106 return self._owner # type: ignore 

107 

108 @property 

109 def group_id(self) -> str: 

110 self._require_valid("access group_id") 

111 assert self._group is not None # for mypy 

112 return self._group.doc_id 

113 

114 @property 

115 @override 

116 def doc_id(self) -> str: 

117 return self.group.doc_id 

118 

119 @override 

120 def validate(self) -> bool: 

121 """Validate that all required models exist and have doc_ids.""" 

122 return self._is_model_valid(self._group) and self._is_model_valid(self._owner) 

123 

124 @property 

125 @override 

126 def _error_messages(self) -> list[str]: 

127 """Build list of validation errors.""" 

128 errors: list[str] = [] 

129 if err := self._validate_model(self._group, "group"): 

130 errors.append(err) 

131 if err := self._validate_model(self._owner, "owner"): 

132 errors.append(err) 

133 return errors