Coverage for polar/oauth2/sub_type.py: 50%

46 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-12-05 17:15 +0000

1from enum import StrEnum 1ab

2from typing import TYPE_CHECKING, Literal, TypeGuard 1ab

3from uuid import UUID 1ab

4 

5from sqlalchemy import ForeignKey, String, Uuid 1ab

6from sqlalchemy.ext.hybrid import hybrid_property 1ab

7from sqlalchemy.orm import Mapped, declared_attr, mapped_column, relationship 1ab

8 

9if TYPE_CHECKING: 9 ↛ 10line 9 didn't jump to line 10 because the condition on line 9 was never true1ab

10 from polar.models import Organization, User 

11 

12 

13class SubType(StrEnum): 1ab

14 user = "user" 1ab

15 organization = "organization" 1ab

16 

17 

18SubTypeValue = tuple[SubType, "User | Organization"] 1ab

19 

20 

21def is_sub_user(v: SubTypeValue) -> TypeGuard[tuple[Literal[SubType.user], "User"]]: 1ab

22 return v[0] == SubType.user 

23 

24 

25def is_sub_organization( 1ab

26 v: SubTypeValue, 

27) -> TypeGuard[tuple[Literal[SubType.organization], "Organization"]]: 

28 return v[0] == SubType.organization 

29 

30 

31class SubTypeModelMixin: 1ab

32 sub_type: Mapped[SubType] = mapped_column(String, nullable=False) 1ab

33 user_id: Mapped[UUID | None] = mapped_column( 1ab

34 Uuid, ForeignKey("users.id", ondelete="cascade"), nullable=True 

35 ) 

36 organization_id: Mapped[UUID | None] = mapped_column( 1ab

37 Uuid, ForeignKey("organizations.id", ondelete="cascade"), nullable=True 

38 ) 

39 

40 @declared_attr 1ab

41 def user(cls) -> Mapped["User | None"]: 1ab

42 return relationship("User", lazy="joined") 1ab

43 

44 @declared_attr 1ab

45 def organization(cls) -> Mapped["Organization | None"]: 1ab

46 return relationship("Organization", lazy="joined") 1ab

47 

48 @hybrid_property 1ab

49 def sub(self) -> "User | Organization": 1ab

50 sub: User | Organization | None = None 

51 if self.sub_type == SubType.user: 

52 sub = self.user 

53 elif self.sub_type == SubType.organization: 

54 sub = self.organization 

55 else: 

56 raise NotImplementedError() 

57 

58 if sub is None: 

59 raise ValueError("Sub is not found.") 

60 

61 return sub 

62 

63 @sub.inplace.setter 1ab

64 def _sub_setter(self, value: "User | Organization") -> None: 1ab

65 if self.sub_type == SubType.user: 

66 self.user_id = value.id 

67 elif self.sub_type == SubType.organization: 

68 self.organization_id = value.id 

69 else: 

70 raise NotImplementedError() 

71 

72 def get_sub_type_value(self) -> SubTypeValue: 1ab

73 return self.sub_type, self.sub