f3-data-models 0.3.7__py3-none-any.whl → 0.4.0__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.
f3_data_models/models.py CHANGED
@@ -1,6 +1,5 @@
1
1
  from datetime import datetime, date, time
2
2
  from typing import Any, Dict, List, Optional
3
- import uuid
4
3
  from sqlalchemy import (
5
4
  ARRAY,
6
5
  JSON,
@@ -17,6 +16,7 @@ from sqlalchemy import (
17
16
  UniqueConstraint,
18
17
  Enum,
19
18
  Uuid,
19
+ inspect,
20
20
  )
21
21
  from typing_extensions import Annotated
22
22
  from sqlalchemy.orm import (
@@ -25,11 +25,13 @@ from sqlalchemy.orm import (
25
25
  Mapped,
26
26
  relationship,
27
27
  )
28
+ from sqlalchemy.orm.attributes import InstrumentedAttribute
28
29
  import enum
29
30
 
30
31
  # Custom Annotations
31
32
  time_notz = Annotated[time, TIME(timezone=False)]
32
33
  time_with_tz = Annotated[time, TIME(timezone=True)]
34
+ ts_notz = Annotated[datetime, DateTime(timezone=False)]
33
35
  text = Annotated[str, TEXT]
34
36
  intpk = Annotated[int, mapped_column(Integer, primary_key=True, autoincrement=True)]
35
37
  dt_create = Annotated[
@@ -150,6 +152,26 @@ class Base(DeclarativeBase):
150
152
  if c.key not in ["created", "updated"]
151
153
  }
152
154
 
155
+ def to_update_dict(self) -> Dict[InstrumentedAttribute, Any]:
156
+ update_dict = {}
157
+ mapper = inspect(self).mapper
158
+
159
+ # Add simple attributes
160
+ for attr in mapper.column_attrs:
161
+ if attr.key not in ["created", "updated", "id"]:
162
+ update_dict[attr] = getattr(self, attr.key)
163
+
164
+ # Add relationships
165
+ for rel in mapper.relationships:
166
+ related_value = getattr(self, rel.key)
167
+ if related_value is not None:
168
+ if rel.uselist:
169
+ update_dict[rel] = [item for item in related_value]
170
+ print(rel, update_dict[rel])
171
+ else:
172
+ update_dict[rel] = related_value
173
+ return update_dict
174
+
153
175
  def __repr__(self):
154
176
  """
155
177
  Get a string representation of the model instance.
@@ -641,10 +663,13 @@ class Event(Base):
641
663
  secondary="event_tags_x_events", cascade="expunge", viewonly=True
642
664
  )
643
665
  event_x_event_types: Mapped[List[EventType_x_Event]] = relationship(
644
- back_populates="event"
666
+ back_populates="event", cascade="save-update, merge, delete"
645
667
  )
646
668
  event_x_event_tags: Mapped[Optional[List[EventTag_x_Event]]] = relationship(
647
- back_populates="event"
669
+ back_populates="event", cascade="save-update, merge, delete"
670
+ )
671
+ attendance: Mapped[List["Attendance"]] = relationship(
672
+ back_populates="event", cascade="expunge, delete"
648
673
  )
649
674
 
650
675
 
@@ -819,7 +844,7 @@ class Attendance(Base):
819
844
  innerjoin=False, cascade="expunge", secondary="users", viewonly=True
820
845
  )
821
846
  attendance_x_attendance_types: Mapped[List[Attendance_x_AttendanceType]] = (
822
- relationship(back_populates="attendance")
847
+ relationship(back_populates="attendance", cascade="save-update, merge, delete")
823
848
  )
824
849
  attendance_types: Mapped[List[AttendanceType]] = relationship(
825
850
  secondary="attendance_x_attendance_types",
@@ -980,7 +1005,7 @@ class NextAuthAccount(Base):
980
1005
  provider (text): The provider of the account.
981
1006
  provider_account_id (text): The provider account ID.
982
1007
  refresh_token (Optional[text]): The refresh token.
983
- access_token (text): The access token.
1008
+ access_token (Optional[text]): The access token.
984
1009
  expires_at (Optional[datetime]): The expiration time of the token.
985
1010
  token_type (Optional[text]): The token type.
986
1011
  scope (Optional[text]): The scope of the token.
@@ -997,7 +1022,7 @@ class NextAuthAccount(Base):
997
1022
  provider: Mapped[text] = mapped_column(VARCHAR, primary_key=True)
998
1023
  provider_account_id: Mapped[text] = mapped_column(VARCHAR, primary_key=True)
999
1024
  refresh_token: Mapped[Optional[text]]
1000
- access_token: Mapped[text]
1025
+ access_token: Mapped[Optional[text]]
1001
1026
  expires_at: Mapped[Optional[datetime]]
1002
1027
  token_type: Mapped[Optional[text]]
1003
1028
  scope: Mapped[Optional[text]]
@@ -1014,7 +1039,7 @@ class NextAuthSession(Base):
1014
1039
  Attributes:
1015
1040
  session_token (text): The session token.
1016
1041
  user_id (int): The ID of the associated user.
1017
- expires (date): The expiration time of the session.
1042
+ expires (ts_notz): The expiration time of the session.
1018
1043
  created (datetime): The timestamp when the record was created.
1019
1044
  updated (datetime): The timestamp when the record was last updated.
1020
1045
  """
@@ -1022,8 +1047,8 @@ class NextAuthSession(Base):
1022
1047
  __tablename__ = "auth_sessions"
1023
1048
 
1024
1049
  session_token: Mapped[text] = mapped_column(TEXT, primary_key=True)
1025
- user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
1026
- expires: Mapped[date]
1050
+ user_id: Mapped[int] = mapped_column(ForeignKey("users.id", ondelete="CASCADE"))
1051
+ expires: Mapped[ts_notz]
1027
1052
  created: Mapped[dt_create]
1028
1053
  updated: Mapped[dt_update]
1029
1054
 
@@ -1035,7 +1060,7 @@ class NextAuthVerificationToken(Base):
1035
1060
  Attributes:
1036
1061
  identifier (text): The identifier of the token.
1037
1062
  token (text): The token.
1038
- expires (date): The expiration time of the token.
1063
+ expires (ts_notz): The expiration time of the token.
1039
1064
  created (datetime): The timestamp when the record was created.
1040
1065
  updated (datetime): The timestamp when the record was last updated.
1041
1066
  """
@@ -1044,7 +1069,7 @@ class NextAuthVerificationToken(Base):
1044
1069
 
1045
1070
  identifier: Mapped[text] = mapped_column(VARCHAR, primary_key=True)
1046
1071
  token: Mapped[text] = mapped_column(VARCHAR, primary_key=True)
1047
- expires: Mapped[date]
1072
+ expires: Mapped[ts_notz]
1048
1073
  created: Mapped[dt_create]
1049
1074
  updated: Mapped[dt_update]
1050
1075
 
@@ -1071,7 +1096,7 @@ class UpdateRequest(Base):
1071
1096
  event_day_of_week (Optional[Day_Of_Week]): The day of the week of the event.
1072
1097
  event_name (str): The name of the event.
1073
1098
  event_description (Optional[text]): A description of the event.
1074
- event_recurrence_pattern (Optional[str]): The recurrence pattern of the event.
1099
+ event_recurrence_pattern (Optional[Event_Cadence]): The recurrence pattern of the event.
1075
1100
  event_recurrence_interval (Optional[int]): The recurrence interval of the event.
1076
1101
  event_index_within_interval (Optional[int]): The index within the recurrence interval.
1077
1102
  event_meta (Optional[Dict[str, Any]]): Additional metadata for the event.
@@ -1102,7 +1127,9 @@ class UpdateRequest(Base):
1102
1127
  __tablename__ = "update_requests"
1103
1128
 
1104
1129
  id: Mapped[Uuid] = mapped_column(UUID(as_uuid=True), primary_key=True)
1105
- token: Mapped[Uuid] = mapped_column(UUID(as_uuid=True), default=uuid.uuid4)
1130
+ token: Mapped[Uuid] = mapped_column(
1131
+ UUID(as_uuid=True), server_default=func.gen_random_uuid()
1132
+ )
1106
1133
  region_id: Mapped[int] = mapped_column(ForeignKey("orgs.id"))
1107
1134
  event_id: Mapped[Optional[int]] = mapped_column(ForeignKey("events.id"))
1108
1135
  event_type_ids: Mapped[Optional[List[int]]] = mapped_column(ARRAY(Integer))
@@ -1118,7 +1145,7 @@ class UpdateRequest(Base):
1118
1145
  event_day_of_week: Mapped[Optional[Day_Of_Week]]
1119
1146
  event_name: Mapped[str]
1120
1147
  event_description: Mapped[Optional[text]]
1121
- event_recurrence_pattern: Mapped[Optional[str]] = mapped_column(VARCHAR(length=30))
1148
+ event_recurrence_pattern: Mapped[Optional[Event_Cadence]]
1122
1149
  event_recurrence_interval: Mapped[Optional[int]]
1123
1150
  event_index_within_interval: Mapped[Optional[int]]
1124
1151
  event_meta: Mapped[Optional[Dict[str, Any]]]
f3_data_models/testing.py CHANGED
@@ -12,10 +12,10 @@ def test_update_event():
12
12
  highlight=True,
13
13
  start_date=datetime.date(2025, 2, 17),
14
14
  end_date=datetime.date(2026, 2, 17),
15
- start_time="0500",
15
+ start_time="0400",
16
16
  end_time="0600",
17
17
  event_x_event_types=[
18
- EventType_x_Event(event_type_id=4),
18
+ EventType_x_Event(event_type_id=3),
19
19
  ],
20
20
  recurrence_pattern=Event_Cadence.weekly,
21
21
  day_of_week=Day_Of_Week.monday,
@@ -23,17 +23,11 @@ def test_update_event():
23
23
  index_within_interval=1,
24
24
  name="Test Event",
25
25
  )
26
- update_dict = event.__dict__
27
- DbManager.update_records(Event, [Event.id == 3], update_dict)
26
+ update_dict = event.to_update_dict()
27
+ DbManager.update_record(Event, 3, update_dict)
28
28
 
29
- # with get_session() as session:
30
- # # delete event_x_event_types
31
- # session.query(EventType_x_Event).filter(
32
- # EventType_x_Event.event_id == 3
33
- # ).delete()
34
- # # add event_x_event_types
35
- # session.add(EventType_x_Event(event_id=3, event_type_id=4))
36
- # session.commit()
29
+ # event = DbManager.get(Event, 3)
30
+ DbManager.delete_records(Event, [Event.series_id == 3])
37
31
 
38
32
 
39
33
  if __name__ == "__main__":
f3_data_models/utils.py CHANGED
@@ -1,6 +1,6 @@
1
1
  import os
2
2
  from dataclasses import dataclass
3
- from typing import List, Optional, Tuple, TypeVar
3
+ from typing import List, Optional, Tuple, TypeVar, Type, Generic # noqa
4
4
 
5
5
  import sqlalchemy
6
6
  from sqlalchemy import Select, and_, select, inspect
@@ -89,7 +89,7 @@ def _joinedloads(cls: T, query: Select, joinedloads: list | str) -> Select:
89
89
 
90
90
 
91
91
  class DbManager:
92
- def get(cls: T, id: int, joinedloads: list | str = []) -> T:
92
+ def get(cls: Type[T], id: int, joinedloads: list | str = []) -> T:
93
93
  session = get_session()
94
94
  try:
95
95
  query = select(cls).filter(cls.id == id)
@@ -175,9 +175,9 @@ class DbManager:
175
175
 
176
176
  mapper = class_mapper(cls)
177
177
  relationships = mapper.relationships.keys()
178
- for key, value in fields.items():
178
+ for attr, value in fields.items():
179
+ key = attr.key
179
180
  if hasattr(cls, key) and key not in relationships:
180
- attr = getattr(cls, key)
181
181
  if isinstance(attr, InstrumentedAttribute):
182
182
  setattr(record, key, value)
183
183
  elif key in relationships:
@@ -232,14 +232,16 @@ class DbManager:
232
232
 
233
233
  for obj in objects:
234
234
  # Update simple fields
235
- for key, value in fields.items():
235
+ for attr, value in fields.items():
236
+ key = attr.key
236
237
  if key in valid_attributes and not isinstance(
237
238
  value, InstrumentedList
238
239
  ):
239
240
  setattr(obj, key, value)
240
241
 
241
242
  # Update relationships separately
242
- for key, value in fields.items():
243
+ for attr, value in fields.items():
244
+ key = attr.key
243
245
  if key in valid_relationships:
244
246
  # Handle relationships separately
245
247
  relationship = inspect(cls).mapper.relationships[key]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: f3-data-models
3
- Version: 0.3.7
3
+ Version: 0.4.0
4
4
  Summary: The data schema and models for F3 Nation applications.
5
5
  License: MIT
6
6
  Author: Evan Petzoldt
@@ -0,0 +1,7 @@
1
+ f3_data_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ f3_data_models/models.py,sha256=nYYWcuJl7w_NnTRN28Tt3auKAtjKSIO7QPa0SiFCkHE,45459
3
+ f3_data_models/testing.py,sha256=KmTjMe345-NZCdHNaNnOyL33J8D5oVdqdIhYIKbM8XM,968
4
+ f3_data_models/utils.py,sha256=UpNx1E_kmt8_1vN4fdFSy55yPCoDA2algzof_5EAJ2k,13835
5
+ f3_data_models-0.4.0.dist-info/METADATA,sha256=XoY3AL0bgZbM-Iib_D6mFfeIEXxAqmP9o68ZNYxE0N8,2716
6
+ f3_data_models-0.4.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
7
+ f3_data_models-0.4.0.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- f3_data_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- f3_data_models/models.py,sha256=SLOXwM2BMnlGTwkVZfG3fM9hoksvPkcFRqzpEI4bm2Y,44293
3
- f3_data_models/testing.py,sha256=vetCEBQC8R1hf0TcH3-lINXdlHMVIcjC6OhVWiiFWU0,1204
4
- f3_data_models/utils.py,sha256=5Hg0f1cPMYc-URdTbDTLMiG9rCFN5NskJ4lUHw1a2NU,13747
5
- f3_data_models-0.3.7.dist-info/METADATA,sha256=F34OA9YQW-60PwJ77YytFIHNL_-zMlbew6t23Rrdfm4,2716
6
- f3_data_models-0.3.7.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
7
- f3_data_models-0.3.7.dist-info/RECORD,,