artemis-model 0.1.80__py3-none-any.whl → 0.1.86__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
artemis_model/__init__.py CHANGED
@@ -14,3 +14,4 @@ from artemis_model.track import * # noqa
14
14
  from artemis_model.user import * # noqa
15
15
  from artemis_model.zone import * # noqa
16
16
  from artemis_model.otp import * # noqa
17
+ from artemis_model.device import * # noqa
artemis_model/auth.py CHANGED
@@ -63,6 +63,15 @@ class UserAccountMixin(TimeStampMixin):
63
63
  disabled_reason: Mapped[Optional[str]] = mapped_column(nullable=True)
64
64
  is_onboarded: Mapped[bool] = mapped_column(default=False)
65
65
 
66
+
67
+ @declared_attr
68
+ def devices(cls) -> Mapped[list["Device"]]:
69
+ return relationship(
70
+ "Device",
71
+ secondary="device_user_assoc", # Directly reference the association table
72
+ back_populates="users",
73
+ )
74
+
66
75
  @declared_attr
67
76
  def login_histories(cls) -> Mapped["LoginHistory"]:
68
77
  return relationship("LoginHistory", back_populates="account")
@@ -0,0 +1,78 @@
1
+ import enum
2
+ import uuid
3
+ from datetime import datetime
4
+
5
+ from sqlalchemy import JSON, UUID, Enum, ForeignKey
6
+ from sqlalchemy.orm import Mapped, mapped_column, relationship
7
+ from sqlalchemy.ext.declarative import declared_attr
8
+ from sqlalchemy.ext.associationproxy import AssociationProxy, association_proxy
9
+
10
+ from artemis_model.base import CustomSyncBase, CustomBase, TimeStampMixin
11
+
12
+
13
+ class DeviceControlMode(enum.Enum):
14
+ PLAYER = "player"
15
+ CONTROL = "control"
16
+
17
+
18
+ class DeviceMixin(TimeStampMixin):
19
+ """
20
+ Represents a Jukebox device that can be controlled by multiple users.
21
+ """
22
+ id: Mapped[uuid.UUID] = mapped_column(
23
+ UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
24
+ )
25
+ device_id: Mapped[str] = mapped_column(nullable=False, unique=True, index=True)
26
+ name: Mapped[str] = mapped_column(nullable=False) # e.g., "Living Room Jukebox"
27
+ control_mode: Mapped[DeviceControlMode] = mapped_column(Enum(DeviceControlMode), nullable=True)
28
+ last_seen: Mapped[datetime | None] = mapped_column(nullable=True)
29
+ version: Mapped[int] = mapped_column(default=0)
30
+ device_specs: Mapped[JSON] = mapped_column(JSON, nullable=True)
31
+
32
+ @declared_attr
33
+ def device_user_assoc(cls) -> Mapped[list["DeviceUserAssoc"]]:
34
+ return relationship(cascade="all, delete-orphan")
35
+
36
+ @declared_attr
37
+ def user_ids(cls) -> Mapped[list["UserAccount"] | None]:
38
+ return association_proxy(
39
+ "device_user_assoc",
40
+ "user",
41
+ creator=lambda u: DeviceUserAssoc(user_id=u),
42
+ )
43
+
44
+ @declared_attr
45
+ def users(cls) -> Mapped[list["UserAccount"]]:
46
+ return relationship(
47
+ secondary="device_user_assoc",
48
+ viewonly=True
49
+ )
50
+
51
+
52
+ class DeviceSync(CustomSyncBase, DeviceMixin):
53
+ pass
54
+
55
+
56
+ class Device(CustomBase, DeviceMixin):
57
+ pass
58
+
59
+
60
+ class DeviceUserAssocMixin(TimeStampMixin):
61
+ """
62
+ Association table for many-to-many relationship between UserAccount and Device.
63
+ """
64
+
65
+ device_id: Mapped[uuid.UUID] = mapped_column(
66
+ ForeignKey("device.id"), primary_key=True, nullable=False
67
+ )
68
+ user_id: Mapped[uuid.UUID] = mapped_column(
69
+ ForeignKey("user_account.id"), primary_key=True, nullable=False
70
+ )
71
+
72
+
73
+ class DeviceUserAssocSync(CustomSyncBase, DeviceUserAssocMixin):
74
+ pass
75
+
76
+
77
+ class DeviceUserAssoc(CustomBase, DeviceUserAssocMixin):
78
+ pass
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: artemis-model
3
- Version: 0.1.80
3
+ Version: 0.1.86
4
4
  Summary:
5
5
  Author: Jukeboxy
6
6
  Requires-Python: >=3.10.6,<4.0.0
@@ -1,9 +1,10 @@
1
- artemis_model/__init__.py,sha256=VwCQjY-_A2WqI4wLdUwVKh8diUOE67qkGK_8KqL665k,692
1
+ artemis_model/__init__.py,sha256=ppr3Y8tA0RIhszLWNEIL2eIXzj8ho833nbrejsXPuMk,735
2
2
  artemis_model/album.py,sha256=cnjrE0catTK24uWTrAoRcZUQB3CPt5l8s9PeM2sxLrc,2103
3
3
  artemis_model/artist.py,sha256=Mx2bnl7bxqm2ELjDIePGFfIkQU_DbnfOTc507dzh14g,1577
4
- artemis_model/auth.py,sha256=WVonoYbCE0uvRuPR2Fz1hZJ-xmbyTuBVt6H51X6OfEs,4087
4
+ artemis_model/auth.py,sha256=aJc7G1Uf5zpRXE5ULEoVKcICm45uahhJzb2xhB2yPhM,4340
5
5
  artemis_model/base.py,sha256=21Isonytb_iWfmde4u8LiU6a27h7mkgnwncTAKi9ezY,6768
6
6
  artemis_model/category.py,sha256=jhCZrK-LxPmc0pXmVifAZWdCENssBTzdTmC3nqqZc6s,1761
7
+ artemis_model/device.py,sha256=B9H2X6GOtuUcgSMo0jUIf4GHlR36DhL0eBqy7QYhDqY,2375
7
8
  artemis_model/dj_set.py,sha256=-0rU2xOAJ4vecite8yKFmp9yFLPZurFrdFmYAjPHtso,3848
8
9
  artemis_model/genre.py,sha256=oMs1ZZfr0SZWmWzW9PEPuaNcatfeIx53nk5M3DPodrQ,1615
9
10
  artemis_model/location.py,sha256=T6TlUCXxGyicYtb39dw7XjbCSNECZnMPYahxtOtyEiE,4687
@@ -17,6 +18,6 @@ artemis_model/setting.py,sha256=McWbeDZP45km3VSSwP1BgAmmjO4qCL0pTnOmJVAz0WI,1265
17
18
  artemis_model/track.py,sha256=x8BHKDZl9uQmQH6DWpzH-SEsfecLghOBdBT7qXgN3d0,3865
18
19
  artemis_model/user.py,sha256=ZtZVwavSPoQmYM1_MarMULy-DJa2pH482G_G8su0b6c,2211
19
20
  artemis_model/zone.py,sha256=iGRUtzUwKh9LHT3MOfzzg1DnkPBts_ZBzZVTi2EmIgs,2282
20
- artemis_model-0.1.80.dist-info/METADATA,sha256=ttuEVbWaxFNb5DKPcKBdlMl2Q6vwS4L9NkXkyM9qVGQ,3402
21
- artemis_model-0.1.80.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
22
- artemis_model-0.1.80.dist-info/RECORD,,
21
+ artemis_model-0.1.86.dist-info/METADATA,sha256=Ruxd_li94elI2qUbqKx5C2gttLU4gmTr1owPz9BIQkA,3402
22
+ artemis_model-0.1.86.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
23
+ artemis_model-0.1.86.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.1
2
+ Generator: poetry-core 2.1.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any