f3-data-models 0.4.3__tar.gz → 0.4.6__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: f3-data-models
3
- Version: 0.4.3
3
+ Version: 0.4.6
4
4
  Summary: The data schema and models for F3 Nation applications.
5
5
  License: MIT
6
6
  Author: Evan Petzoldt
@@ -777,13 +777,12 @@ class User(Base):
777
777
  """ # noqa: E501
778
778
 
779
779
  __tablename__ = "users"
780
- __table_args__ = (Index("idx_users_email", func.lower("email"), unique=True),)
781
780
 
782
781
  id: Mapped[intpk]
783
782
  f3_name: Mapped[Optional[str]]
784
783
  first_name: Mapped[Optional[str]]
785
784
  last_name: Mapped[Optional[str]]
786
- email: Mapped[str] = mapped_column(CIText)
785
+ email: Mapped[str] = mapped_column(CIText, unique=True)
787
786
  phone: Mapped[Optional[str]]
788
787
  emergency_contact: Mapped[Optional[str]]
789
788
  emergency_phone: Mapped[Optional[str]]
@@ -0,0 +1,27 @@
1
+ from f3_data_models.models import Location
2
+ from f3_data_models.utils import DbManager
3
+
4
+
5
+ def test_update_event():
6
+ DbManager.update_record(
7
+ Location,
8
+ 2,
9
+ {
10
+ "name": "The Beach",
11
+ "description": None,
12
+ "is_active": True,
13
+ "latitude": 22.0356,
14
+ "longitude": -159.3377,
15
+ "address_street": None,
16
+ "address_street2": None,
17
+ "address_city": None,
18
+ "address_state": None,
19
+ "address_zip": None,
20
+ "address_country": None,
21
+ "org_id": 5,
22
+ },
23
+ )
24
+
25
+
26
+ if __name__ == "__main__":
27
+ test_update_event()
@@ -1,24 +1,20 @@
1
1
  import os
2
2
  from dataclasses import dataclass
3
- from typing import List, Optional, Tuple, TypeVar, Type, Generic # noqa
3
+ from typing import Generic, List, Optional, Tuple, Type, TypeVar # noqa
4
4
 
5
+ import pg8000
5
6
  import sqlalchemy
6
- from sqlalchemy import Select, and_, select, inspect
7
-
7
+ from google.cloud.sql.connector import Connector, IPTypes
8
+ from pydot import Dot
9
+ from sqlalchemy import Select, and_, inspect, select
8
10
  from sqlalchemy.dialects.postgresql import insert
9
11
  from sqlalchemy.engine import Engine
10
- from sqlalchemy.orm import sessionmaker, joinedload
12
+ from sqlalchemy.orm import class_mapper, joinedload, sessionmaker
11
13
  from sqlalchemy.orm.collections import InstrumentedList
14
+ from sqlalchemy_schemadisplay import create_schema_graph
12
15
 
13
16
  from f3_data_models.models import Base
14
17
 
15
- from pydot import Dot
16
- from sqlalchemy_schemadisplay import create_schema_graph
17
- from google.cloud.sql.connector import Connector, IPTypes
18
- import pg8000
19
- from sqlalchemy.orm import class_mapper
20
- from sqlalchemy.orm.attributes import InstrumentedAttribute
21
-
22
18
 
23
19
  @dataclass
24
20
  class DatabaseField:
@@ -53,9 +49,7 @@ def get_engine(echo=False) -> Engine:
53
49
  )
54
50
  return conn
55
51
 
56
- engine = sqlalchemy.create_engine(
57
- "postgresql+pg8000://", creator=get_connection, echo=echo
58
- )
52
+ engine = sqlalchemy.create_engine("postgresql+pg8000://", creator=get_connection, echo=echo)
59
53
  return engine
60
54
 
61
55
 
@@ -81,10 +75,7 @@ T = TypeVar("T")
81
75
 
82
76
  def _joinedloads(cls: T, query: Select, joinedloads: list | str) -> Select:
83
77
  if joinedloads == "all":
84
- joinedloads = [
85
- getattr(cls, relationship.key)
86
- for relationship in cls.__mapper__.relationships
87
- ]
78
+ joinedloads = [getattr(cls, relationship.key) for relationship in cls.__mapper__.relationships]
88
79
  return query.options(*[joinedload(load) for load in joinedloads])
89
80
 
90
81
 
@@ -101,9 +92,7 @@ class DbManager:
101
92
  session.rollback()
102
93
  close_session(session)
103
94
 
104
- def find_records(
105
- cls: T, filters: Optional[List], joinedloads: List | str = []
106
- ) -> List[T]:
95
+ def find_records(cls: T, filters: Optional[List], joinedloads: List | str = []) -> List[T]:
107
96
  session = get_session()
108
97
  try:
109
98
  query = select(cls)
@@ -117,9 +106,7 @@ class DbManager:
117
106
  session.rollback()
118
107
  close_session(session)
119
108
 
120
- def find_first_record(
121
- cls: T, filters: Optional[List], joinedloads: List | str = []
122
- ) -> T:
109
+ def find_first_record(cls: T, filters: Optional[List], joinedloads: List | str = []) -> T:
123
110
  session = get_session()
124
111
  try:
125
112
  query = select(cls)
@@ -136,21 +123,14 @@ class DbManager:
136
123
  def find_join_records2(left_cls: T, right_cls: T, filters) -> List[Tuple[T]]:
137
124
  session = get_session()
138
125
  try:
139
- records = (
140
- session.query(left_cls, right_cls)
141
- .join(right_cls)
142
- .filter(and_(*filters))
143
- .all()
144
- )
126
+ records = session.query(left_cls, right_cls).join(right_cls).filter(and_(*filters)).all()
145
127
  session.expunge_all()
146
128
  return records
147
129
  finally:
148
130
  session.rollback()
149
131
  close_session(session)
150
132
 
151
- def find_join_records3(
152
- left_cls: T, right_cls1: T, right_cls2: T, filters, left_join=False
153
- ) -> List[Tuple[T]]:
133
+ def find_join_records3(left_cls: T, right_cls1: T, right_cls2: T, filters, left_join=False) -> List[Tuple[T]]:
154
134
  session = get_session()
155
135
  try:
156
136
  records = (
@@ -176,10 +156,14 @@ class DbManager:
176
156
  mapper = class_mapper(cls)
177
157
  relationships = mapper.relationships.keys()
178
158
  for attr, value in fields.items():
179
- key = attr.key
159
+ key = attr if isinstance(attr, str) else attr.key
160
+ print(f"key: {key}, value: {value}")
180
161
  if hasattr(cls, key) and key not in relationships:
181
- if isinstance(attr, InstrumentedAttribute):
182
- setattr(record, key, value)
162
+ setattr(record, key, value)
163
+ # if isinstance(attr, InstrumentedAttribute):
164
+ # setattr(record, key, value)
165
+ # else:
166
+ # setattr(record, key, value)
183
167
  elif key in relationships:
184
168
  # Handle relationships separately
185
169
  relationship = mapper.relationships[key]
@@ -194,27 +178,21 @@ class DbManager:
194
178
  if isinstance(value, list) and og_primary_key:
195
179
  # Delete existing related records
196
180
  related_class = relationship.mapper.class_
197
- related_relationships = class_mapper(
198
- related_class
199
- ).relationships.keys()
200
- session.query(related_class).filter(
201
- getattr(related_class, og_primary_key) == id
202
- ).delete()
181
+ related_relationships = class_mapper(related_class).relationships.keys()
182
+ session.query(related_class).filter(getattr(related_class, og_primary_key) == id).delete()
203
183
  # Add new related records
204
184
  items = [item.__dict__ for item in value]
205
185
  for related_item in items:
206
186
  update_dict = {
207
187
  k: v
208
188
  for k, v in related_item.items()
209
- if hasattr(related_class, k)
210
- and k not in related_relationships
189
+ if hasattr(related_class, k) and k not in related_relationships
211
190
  }
212
- related_record = related_class(
213
- **{og_primary_key: id, **update_dict}
214
- )
191
+ related_record = related_class(**{og_primary_key: id, **update_dict})
215
192
  session.add(related_record)
216
193
 
217
194
  try:
195
+ print(record)
218
196
  session.commit()
219
197
  except pg8000.IntegrityError as e:
220
198
  session.rollback()
@@ -234,9 +212,7 @@ class DbManager:
234
212
  # Update simple fields
235
213
  for attr, value in fields.items():
236
214
  key = attr.key
237
- if key in valid_attributes and not isinstance(
238
- value, InstrumentedList
239
- ):
215
+ if key in valid_attributes and not isinstance(value, InstrumentedList):
240
216
  setattr(obj, key, value)
241
217
 
242
218
  # Update relationships separately
@@ -256,9 +232,7 @@ class DbManager:
256
232
  if isinstance(value, list) and og_primary_key:
257
233
  # Delete existing related records
258
234
  related_class = relationship.mapper.class_
259
- related_relationships = class_mapper(
260
- related_class
261
- ).relationships.keys()
235
+ related_relationships = class_mapper(related_class).relationships.keys()
262
236
  session.query(related_class).filter(
263
237
  getattr(related_class, og_primary_key) == obj.id
264
238
  ).delete()
@@ -268,12 +242,9 @@ class DbManager:
268
242
  update_dict = {
269
243
  k: v
270
244
  for k, v in related_item.items()
271
- if hasattr(related_class, k)
272
- and k not in related_relationships
245
+ if hasattr(related_class, k) and k not in related_relationships
273
246
  }
274
- related_record = related_class(
275
- **{og_primary_key: obj.id, **update_dict}
276
- )
247
+ related_record = related_class(**{og_primary_key: obj.id, **update_dict})
277
248
  session.add(related_record)
278
249
 
279
250
  session.flush()
@@ -307,11 +278,7 @@ class DbManager:
307
278
  session = get_session()
308
279
  try:
309
280
  for record in records:
310
- record_dict = {
311
- k: v
312
- for k, v in record.__dict__.items()
313
- if k != "_sa_instance_state"
314
- }
281
+ record_dict = {k: v for k, v in record.__dict__.items() if k != "_sa_instance_state"}
315
282
  stmt = insert(cls).values(record_dict).on_conflict_do_nothing()
316
283
  session.execute(stmt)
317
284
  session.flush()
@@ -323,15 +290,9 @@ class DbManager:
323
290
  session = get_session()
324
291
  try:
325
292
  for record in records:
326
- record_dict = {
327
- k: v
328
- for k, v in record.__dict__.items()
329
- if k != "_sa_instance_state"
330
- }
293
+ record_dict = {k: v for k, v in record.__dict__.items() if k != "_sa_instance_state"}
331
294
  stmt = insert(cls).values(record_dict)
332
- update_dict = {
333
- c.name: getattr(record, c.name) for c in cls.__table__.columns
334
- }
295
+ update_dict = {c.name: getattr(record, c.name) for c in cls.__table__.columns}
335
296
  stmt = stmt.on_conflict_do_update(
336
297
  index_elements=[cls.__table__.primary_key.columns.keys()],
337
298
  set_=update_dict,
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "f3-data-models"
3
- version = "0.4.3"
3
+ version = "0.4.6"
4
4
  description = "The data schema and models for F3 Nation applications."
5
5
  authors = ["Evan Petzoldt <evan.petzoldt@protonmail.com>"]
6
6
  readme = "README.md"
@@ -1,34 +0,0 @@
1
- from f3_data_models.models import Event, Day_Of_Week, Event_Cadence, EventType_x_Event
2
- import datetime
3
- from f3_data_models.utils import DbManager
4
-
5
-
6
- def test_update_event():
7
- event = Event(
8
- org_id=3,
9
- location_id=2,
10
- is_series=True,
11
- is_active=True,
12
- highlight=True,
13
- start_date=datetime.date(2025, 2, 17),
14
- end_date=datetime.date(2026, 2, 17),
15
- start_time="0400",
16
- end_time="0600",
17
- event_x_event_types=[
18
- EventType_x_Event(event_type_id=3),
19
- ],
20
- recurrence_pattern=Event_Cadence.weekly,
21
- day_of_week=Day_Of_Week.monday,
22
- recurrence_interval=1,
23
- index_within_interval=1,
24
- name="Test Event",
25
- )
26
- update_dict = event.to_update_dict()
27
- DbManager.update_record(Event, 3, update_dict)
28
-
29
- # event = DbManager.get(Event, 3)
30
- DbManager.delete_records(Event, [Event.series_id == 3])
31
-
32
-
33
- if __name__ == "__main__":
34
- test_update_event()
File without changes