f3-data-models 0.4.3__py3-none-any.whl → 0.4.6__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 +1 -2
- f3_data_models/testing.py +18 -25
- f3_data_models/utils.py +32 -71
- {f3_data_models-0.4.3.dist-info → f3_data_models-0.4.6.dist-info}/METADATA +1 -1
- f3_data_models-0.4.6.dist-info/RECORD +7 -0
- {f3_data_models-0.4.3.dist-info → f3_data_models-0.4.6.dist-info}/WHEEL +1 -1
- f3_data_models-0.4.3.dist-info/RECORD +0 -7
f3_data_models/models.py
CHANGED
@@ -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]]
|
f3_data_models/testing.py
CHANGED
@@ -1,33 +1,26 @@
|
|
1
|
-
from f3_data_models.models import
|
2
|
-
import datetime
|
1
|
+
from f3_data_models.models import Location
|
3
2
|
from f3_data_models.utils import DbManager
|
4
3
|
|
5
4
|
|
6
5
|
def test_update_event():
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
name="Test 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
|
+
},
|
25
23
|
)
|
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
24
|
|
32
25
|
|
33
26
|
if __name__ == "__main__":
|
f3_data_models/utils.py
CHANGED
@@ -1,24 +1,20 @@
|
|
1
1
|
import os
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import List, Optional, Tuple,
|
3
|
+
from typing import Generic, List, Optional, Tuple, Type, TypeVar # noqa
|
4
4
|
|
5
|
+
import pg8000
|
5
6
|
import sqlalchemy
|
6
|
-
from
|
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
|
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
|
-
|
182
|
-
|
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
|
-
|
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,
|
@@ -0,0 +1,7 @@
|
|
1
|
+
f3_data_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
+
f3_data_models/models.py,sha256=q_oQEe2Ccvcnl5l4Zf4fYNoogiT_1SSa8vMNmbW_QH8,45973
|
3
|
+
f3_data_models/testing.py,sha256=UE88nhMrlflrPqeBM8uHcqCAc_p43q_jsSrPep8f01c,654
|
4
|
+
f3_data_models/utils.py,sha256=xFhMU6imwWGdH2KdqcAsddILR7FuAftDwfn9tIcLiwM,13208
|
5
|
+
f3_data_models-0.4.6.dist-info/METADATA,sha256=UToOyWmRygdsIbvl0EzLi_DtGaYEinW1HVysk32Pykg,2766
|
6
|
+
f3_data_models-0.4.6.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
7
|
+
f3_data_models-0.4.6.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=3bJUsEC-lENYt5ezqN0pbUQTV3znndLnWnrJVQ3vJOk,46043
|
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.3.dist-info/METADATA,sha256=5_8Rauj6G4fOY5QGaXtgl0nsdUfATnUGBPLISPPCJ_Y,2766
|
6
|
-
f3_data_models-0.4.3.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
7
|
-
f3_data_models-0.4.3.dist-info/RECORD,,
|