belgie-alchemy 0.1.0a4__py3-none-any.whl → 0.3.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.
@@ -1,493 +0,0 @@
1
- from datetime import UTC, datetime, timedelta
2
- from uuid import uuid4
3
-
4
- import pytest
5
- from sqlalchemy.ext.asyncio import AsyncSession
6
-
7
- from belgie_alchemy import AlchemyAdapter
8
- from belgie_alchemy.__tests__.fixtures.models import Account, OAuthState, Session, User
9
-
10
-
11
- @pytest.fixture
12
- def adapter(alchemy_session: AsyncSession) -> AlchemyAdapter: # noqa: ARG001
13
- return AlchemyAdapter(
14
- user=User,
15
- account=Account,
16
- session=Session,
17
- oauth_state=OAuthState,
18
- )
19
-
20
-
21
- @pytest.mark.asyncio
22
- async def test_create_user(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
23
- user = await adapter.create_user(
24
- alchemy_session,
25
- email="test@example.com",
26
- name="Test User",
27
- email_verified=True,
28
- )
29
-
30
- assert user.email == "test@example.com"
31
- assert user.name == "Test User"
32
- assert user.email_verified is True
33
- assert user.id is not None
34
- assert user.created_at is not None
35
-
36
-
37
- @pytest.mark.asyncio
38
- async def test_get_user_by_id(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
39
- created_user = await adapter.create_user(
40
- alchemy_session,
41
- email="test@example.com",
42
- name="Test User",
43
- )
44
-
45
- found_user = await adapter.get_user_by_id(alchemy_session, created_user.id)
46
-
47
- assert found_user is not None
48
- assert found_user.id == created_user.id
49
- assert found_user.email == "test@example.com"
50
-
51
-
52
- @pytest.mark.asyncio
53
- async def test_get_user_by_id_not_found(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
54
- user = await adapter.get_user_by_id(alchemy_session, uuid4())
55
- assert user is None
56
-
57
-
58
- @pytest.mark.asyncio
59
- async def test_get_user_by_email(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
60
- await adapter.create_user(
61
- alchemy_session,
62
- email="test@example.com",
63
- name="Test User",
64
- )
65
-
66
- user = await adapter.get_user_by_email(alchemy_session, "test@example.com")
67
-
68
- assert user is not None
69
- assert user.email == "test@example.com"
70
-
71
-
72
- @pytest.mark.asyncio
73
- async def test_get_user_by_email_not_found(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
74
- user = await adapter.get_user_by_email(alchemy_session, "nonexistent@example.com")
75
- assert user is None
76
-
77
-
78
- @pytest.mark.asyncio
79
- async def test_update_user(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
80
- user = await adapter.create_user(
81
- alchemy_session,
82
- email="test@example.com",
83
- name="Test User",
84
- )
85
-
86
- updated_user = await adapter.update_user(
87
- alchemy_session,
88
- user.id,
89
- name="Updated Name",
90
- email_verified=True,
91
- )
92
-
93
- assert updated_user is not None
94
- assert updated_user.name == "Updated Name"
95
- assert updated_user.email_verified is True
96
-
97
-
98
- @pytest.mark.asyncio
99
- async def test_update_user_not_found(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
100
- updated_user = await adapter.update_user(
101
- alchemy_session,
102
- uuid4(),
103
- name="Updated Name",
104
- )
105
- assert updated_user is None
106
-
107
-
108
- @pytest.mark.asyncio
109
- async def test_create_account(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
110
- user = await adapter.create_user(
111
- alchemy_session,
112
- email="test@example.com",
113
- )
114
-
115
- account = await adapter.create_account(
116
- alchemy_session,
117
- user_id=user.id,
118
- provider="google",
119
- provider_account_id="12345",
120
- access_token="token",
121
- refresh_token="refresh",
122
- expires_at=datetime.now(UTC) + timedelta(hours=1),
123
- token_type="Bearer",
124
- scope="openid email",
125
- id_token="id_token",
126
- )
127
-
128
- assert account.user_id == user.id
129
- assert account.provider == "google"
130
- assert account.provider_account_id == "12345"
131
- assert account.access_token == "token" # noqa: S105
132
- assert account.refresh_token == "refresh" # noqa: S105
133
- assert account.token_type == "Bearer" # noqa: S105
134
-
135
-
136
- @pytest.mark.asyncio
137
- async def test_get_account(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
138
- user = await adapter.create_user(
139
- alchemy_session,
140
- email="test@example.com",
141
- )
142
-
143
- await adapter.create_account(
144
- alchemy_session,
145
- user_id=user.id,
146
- provider="google",
147
- provider_account_id="12345",
148
- )
149
-
150
- account = await adapter.get_account(alchemy_session, "google", "12345")
151
-
152
- assert account is not None
153
- assert account.provider == "google"
154
- assert account.provider_account_id == "12345"
155
-
156
-
157
- @pytest.mark.asyncio
158
- async def test_get_account_not_found(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
159
- account = await adapter.get_account(alchemy_session, "google", "nonexistent")
160
- assert account is None
161
-
162
-
163
- @pytest.mark.asyncio
164
- async def test_create_session(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
165
- user = await adapter.create_user(
166
- alchemy_session,
167
- email="test@example.com",
168
- )
169
-
170
- expires_at = datetime.now(UTC) + timedelta(days=7)
171
- session = await adapter.create_session(
172
- alchemy_session,
173
- user_id=user.id,
174
- expires_at=expires_at,
175
- ip_address="127.0.0.1",
176
- user_agent="Test Agent",
177
- )
178
-
179
- assert session.user_id == user.id
180
- assert session.expires_at.replace(tzinfo=UTC) == expires_at
181
- assert session.ip_address == "127.0.0.1"
182
- assert session.user_agent == "Test Agent"
183
-
184
-
185
- @pytest.mark.asyncio
186
- async def test_get_session(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
187
- user = await adapter.create_user(
188
- alchemy_session,
189
- email="test@example.com",
190
- )
191
-
192
- created_session = await adapter.create_session(
193
- alchemy_session,
194
- user_id=user.id,
195
- expires_at=datetime.now(UTC) + timedelta(days=7),
196
- )
197
-
198
- found_session = await adapter.get_session(alchemy_session, created_session.id)
199
-
200
- assert found_session is not None
201
- assert found_session.id == created_session.id
202
-
203
-
204
- @pytest.mark.asyncio
205
- async def test_get_session_not_found(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
206
- session = await adapter.get_session(alchemy_session, uuid4())
207
- assert session is None
208
-
209
-
210
- @pytest.mark.asyncio
211
- async def test_update_session(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
212
- user = await adapter.create_user(
213
- alchemy_session,
214
- email="test@example.com",
215
- )
216
-
217
- session = await adapter.create_session(
218
- alchemy_session,
219
- user_id=user.id,
220
- expires_at=datetime.now(UTC) + timedelta(days=7),
221
- )
222
-
223
- new_expires = datetime.now(UTC) + timedelta(days=14)
224
- updated_session = await adapter.update_session(
225
- alchemy_session,
226
- session.id,
227
- expires_at=new_expires,
228
- ip_address="192.168.1.1",
229
- )
230
-
231
- assert updated_session is not None
232
- assert updated_session.expires_at.replace(tzinfo=UTC) == new_expires
233
- assert updated_session.ip_address == "192.168.1.1"
234
-
235
-
236
- @pytest.mark.asyncio
237
- async def test_update_session_not_found(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
238
- updated_session = await adapter.update_session(
239
- alchemy_session,
240
- uuid4(),
241
- expires_at=datetime.now(UTC) + timedelta(days=7),
242
- )
243
- assert updated_session is None
244
-
245
-
246
- @pytest.mark.asyncio
247
- async def test_delete_session(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
248
- user = await adapter.create_user(
249
- alchemy_session,
250
- email="test@example.com",
251
- )
252
-
253
- session = await adapter.create_session(
254
- alchemy_session,
255
- user_id=user.id,
256
- expires_at=datetime.now(UTC) + timedelta(days=7),
257
- )
258
-
259
- deleted = await adapter.delete_session(alchemy_session, session.id)
260
- assert deleted is True
261
-
262
- found = await adapter.get_session(alchemy_session, session.id)
263
- assert found is None
264
-
265
-
266
- @pytest.mark.asyncio
267
- async def test_delete_session_not_found(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
268
- deleted = await adapter.delete_session(alchemy_session, uuid4())
269
- assert deleted is False
270
-
271
-
272
- @pytest.mark.asyncio
273
- async def test_delete_expired_sessions(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
274
- user = await adapter.create_user(
275
- alchemy_session,
276
- email="test@example.com",
277
- )
278
-
279
- await adapter.create_session(
280
- alchemy_session,
281
- user_id=user.id,
282
- expires_at=datetime.now(UTC) - timedelta(days=1),
283
- )
284
-
285
- await adapter.create_session(
286
- alchemy_session,
287
- user_id=user.id,
288
- expires_at=datetime.now(UTC) + timedelta(days=7),
289
- )
290
-
291
- count = await adapter.delete_expired_sessions(alchemy_session)
292
- assert count == 1
293
-
294
-
295
- @pytest.mark.asyncio
296
- async def test_create_oauth_state(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
297
- expires_at = datetime.now(UTC) + timedelta(minutes=10)
298
- oauth_state = await adapter.create_oauth_state(
299
- alchemy_session,
300
- state="random_state_123",
301
- expires_at=expires_at,
302
- code_verifier="verifier_abc",
303
- redirect_url="/dashboard",
304
- )
305
-
306
- assert oauth_state.state == "random_state_123"
307
- assert oauth_state.code_verifier == "verifier_abc"
308
- assert oauth_state.redirect_url == "/dashboard"
309
- assert oauth_state.expires_at.replace(tzinfo=UTC) == expires_at
310
-
311
-
312
- @pytest.mark.asyncio
313
- async def test_get_oauth_state(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
314
- await adapter.create_oauth_state(
315
- alchemy_session,
316
- state="random_state_123",
317
- expires_at=datetime.now(UTC) + timedelta(minutes=10),
318
- )
319
-
320
- oauth_state = await adapter.get_oauth_state(alchemy_session, "random_state_123")
321
-
322
- assert oauth_state is not None
323
- assert oauth_state.state == "random_state_123"
324
-
325
-
326
- @pytest.mark.asyncio
327
- async def test_get_oauth_state_not_found(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
328
- oauth_state = await adapter.get_oauth_state(alchemy_session, "nonexistent")
329
- assert oauth_state is None
330
-
331
-
332
- @pytest.mark.asyncio
333
- async def test_delete_oauth_state(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
334
- await adapter.create_oauth_state(
335
- alchemy_session,
336
- state="random_state_123",
337
- expires_at=datetime.now(UTC) + timedelta(minutes=10),
338
- )
339
-
340
- deleted = await adapter.delete_oauth_state(alchemy_session, "random_state_123")
341
- assert deleted is True
342
-
343
- found = await adapter.get_oauth_state(alchemy_session, "random_state_123")
344
- assert found is None
345
-
346
-
347
- @pytest.mark.asyncio
348
- async def test_delete_oauth_state_not_found(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
349
- deleted = await adapter.delete_oauth_state(alchemy_session, "nonexistent")
350
- assert deleted is False
351
-
352
-
353
- @pytest.mark.asyncio
354
- async def test_user_with_custom_fields(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
355
- user_data = User(
356
- email="custom@example.com",
357
- email_verified=True,
358
- name="Custom User",
359
- image=None,
360
- custom_field="custom value",
361
- )
362
- alchemy_session.add(user_data)
363
- await alchemy_session.commit()
364
-
365
- found = await adapter.get_user_by_email(alchemy_session, "custom@example.com")
366
- assert found is not None
367
- assert found.custom_field == "custom value"
368
-
369
-
370
- @pytest.mark.asyncio
371
- async def test_delete_user_deletes_user(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
372
- user = await adapter.create_user(alchemy_session, email="delete@example.com", name="Delete User")
373
-
374
- deleted = await adapter.delete_user(alchemy_session, user.id)
375
-
376
- assert deleted is True
377
- assert await adapter.get_user_by_id(alchemy_session, user.id) is None
378
-
379
-
380
- @pytest.mark.asyncio
381
- async def test_delete_user_deletes_sessions(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
382
- user = await adapter.create_user(alchemy_session, email="delete@example.com", name="Delete User")
383
-
384
- expires_at = datetime.now(UTC) + timedelta(days=1)
385
- session1 = await adapter.create_session(alchemy_session, user.id, expires_at.replace(tzinfo=None))
386
- session2 = await adapter.create_session(alchemy_session, user.id, expires_at.replace(tzinfo=None))
387
-
388
- await adapter.delete_user(alchemy_session, user.id)
389
-
390
- assert await adapter.get_session(alchemy_session, session1.id) is None
391
- assert await adapter.get_session(alchemy_session, session2.id) is None
392
-
393
-
394
- @pytest.mark.asyncio
395
- async def test_delete_user_deletes_accounts(adapter: AlchemyAdapter, alchemy_session: AsyncSession) -> None:
396
- user = await adapter.create_user(alchemy_session, email="delete@example.com", name="Delete User")
397
-
398
- await adapter.create_account(
399
- alchemy_session,
400
- user.id,
401
- "google",
402
- "google-123",
403
- access_token="token123",
404
- )
405
-
406
- await adapter.delete_user(alchemy_session, user.id)
407
-
408
- assert await adapter.get_account(alchemy_session, "google", "google-123") is None
409
-
410
-
411
- @pytest.mark.asyncio
412
- async def test_delete_user_deletes_all_related_data(
413
- adapter: AlchemyAdapter,
414
- alchemy_session: AsyncSession,
415
- ) -> None:
416
- user = await adapter.create_user(alchemy_session, email="delete@example.com", name="Delete User")
417
-
418
- expires_at = datetime.now(UTC) + timedelta(days=1)
419
- session1 = await adapter.create_session(alchemy_session, user.id, expires_at.replace(tzinfo=None))
420
- session2 = await adapter.create_session(alchemy_session, user.id, expires_at.replace(tzinfo=None))
421
-
422
- await adapter.create_account(
423
- alchemy_session,
424
- user.id,
425
- "google",
426
- "google-123",
427
- access_token="token123",
428
- )
429
- await adapter.create_account(
430
- alchemy_session,
431
- user.id,
432
- "github",
433
- "github-456",
434
- access_token="token456",
435
- )
436
-
437
- deleted = await adapter.delete_user(alchemy_session, user.id)
438
-
439
- assert deleted is True
440
- assert await adapter.get_user_by_id(alchemy_session, user.id) is None
441
- assert await adapter.get_session(alchemy_session, session1.id) is None
442
- assert await adapter.get_session(alchemy_session, session2.id) is None
443
- assert await adapter.get_account(alchemy_session, "google", "google-123") is None
444
- assert await adapter.get_account(alchemy_session, "github", "github-456") is None
445
-
446
-
447
- @pytest.mark.asyncio
448
- async def test_delete_user_returns_false_if_user_not_found(
449
- adapter: AlchemyAdapter,
450
- alchemy_session: AsyncSession,
451
- ) -> None:
452
- fake_user_id = uuid4()
453
- deleted = await adapter.delete_user(alchemy_session, fake_user_id)
454
-
455
- assert deleted is False
456
-
457
-
458
- @pytest.mark.asyncio
459
- async def test_delete_user_only_deletes_target_users_data(
460
- adapter: AlchemyAdapter,
461
- alchemy_session: AsyncSession,
462
- ) -> None:
463
- user1 = await adapter.create_user(alchemy_session, email="user1@example.com", name="User 1")
464
- user2 = await adapter.create_user(alchemy_session, email="user2@example.com", name="User 2")
465
-
466
- expires_at = datetime.now(UTC) + timedelta(days=1)
467
- session1 = await adapter.create_session(alchemy_session, user1.id, expires_at.replace(tzinfo=None))
468
- session2 = await adapter.create_session(alchemy_session, user2.id, expires_at.replace(tzinfo=None))
469
-
470
- await adapter.create_account(
471
- alchemy_session,
472
- user1.id,
473
- "google",
474
- "google-user1",
475
- access_token="token1",
476
- )
477
- await adapter.create_account(
478
- alchemy_session,
479
- user2.id,
480
- "google",
481
- "google-user2",
482
- access_token="token2",
483
- )
484
-
485
- await adapter.delete_user(alchemy_session, user1.id)
486
-
487
- assert await adapter.get_user_by_id(alchemy_session, user1.id) is None
488
- assert await adapter.get_session(alchemy_session, session1.id) is None
489
- assert await adapter.get_account(alchemy_session, "google", "google-user1") is None
490
-
491
- assert await adapter.get_user_by_id(alchemy_session, user2.id) is not None
492
- assert await adapter.get_session(alchemy_session, session2.id) is not None
493
- assert await adapter.get_account(alchemy_session, "google", "google-user2") is not None
File without changes
@@ -1,91 +0,0 @@
1
- from datetime import UTC, datetime, timedelta
2
-
3
- import pytest
4
- from sqlalchemy import select
5
- from sqlalchemy.exc import IntegrityError
6
- from sqlalchemy.ext.asyncio import AsyncSession
7
-
8
- from belgie_alchemy.__tests__.fixtures.models import Account, OAuthState, Session, User
9
-
10
-
11
- def test_user_model_structure() -> None:
12
- """Verify User model demonstrates proper structure."""
13
- assert User.__tablename__ == "users"
14
- assert not getattr(User, "__abstract__", False)
15
- assert hasattr(User, "email")
16
- assert hasattr(User, "scopes")
17
-
18
-
19
- def test_user_has_scopes_field() -> None:
20
- """Verify User has scopes field that accepts list of strings."""
21
- user = User(email="test@example.com")
22
- user.scopes = ["read", "write"]
23
- assert user.scopes == ["read", "write"]
24
-
25
-
26
- def test_user_relationships_defined() -> None:
27
- """Verify User has bidirectional relationships defined."""
28
- assert hasattr(User, "accounts")
29
- assert hasattr(User, "sessions")
30
- assert hasattr(User, "oauth_states")
31
-
32
-
33
- @pytest.mark.asyncio
34
- async def test_account_unique_constraint(alchemy_session: AsyncSession) -> None:
35
- user = User(email="auth@example.com")
36
- alchemy_session.add(user)
37
- await alchemy_session.commit()
38
-
39
- account = Account(
40
- user_id=user.id,
41
- provider="google",
42
- provider_account_id="abc",
43
- )
44
- alchemy_session.add(account)
45
- await alchemy_session.commit()
46
-
47
- duplicate = Account(
48
- user_id=user.id,
49
- provider="google",
50
- provider_account_id="abc",
51
- )
52
- alchemy_session.add(duplicate)
53
- with pytest.raises(IntegrityError):
54
- await alchemy_session.commit()
55
- await alchemy_session.rollback()
56
-
57
-
58
- @pytest.mark.asyncio
59
- async def test_session_relationship(alchemy_session: AsyncSession) -> None:
60
- user = User(email="session@example.com")
61
- alchemy_session.add(user)
62
- await alchemy_session.commit()
63
-
64
- session = Session(
65
- user_id=user.id,
66
- expires_at=datetime.now(UTC) + timedelta(days=1),
67
- )
68
- alchemy_session.add(session)
69
- await alchemy_session.commit()
70
-
71
- refreshed = await alchemy_session.get(User, user.id)
72
- assert refreshed is not None
73
- await alchemy_session.refresh(refreshed, attribute_names=["sessions"])
74
- assert len(refreshed.sessions) == 1
75
-
76
-
77
- @pytest.mark.asyncio
78
- async def test_oauth_state_optional_user(alchemy_session: AsyncSession) -> None:
79
- state = OAuthState(
80
- state="abc",
81
- code_verifier=None,
82
- redirect_url=None,
83
- expires_at=datetime.now(UTC) + timedelta(minutes=5),
84
- user_id=None,
85
- )
86
- alchemy_session.add(state)
87
- await alchemy_session.commit()
88
-
89
- rows = await alchemy_session.execute(select(OAuthState))
90
- stored = rows.scalar_one()
91
- assert stored.user is None
File without changes
@@ -1,90 +0,0 @@
1
- from datetime import UTC, datetime
2
- from pathlib import Path
3
- from tempfile import TemporaryDirectory
4
-
5
- import pytest
6
- from sqlalchemy import Integer, event, select
7
- from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
8
- from sqlalchemy.orm import Mapped, mapped_column
9
-
10
- from belgie_alchemy.__tests__.fixtures.models import User
11
- from belgie_alchemy.base import NAMING_CONVENTION, Base
12
- from belgie_alchemy.types import DateTimeUTC
13
-
14
-
15
- def test_type_annotation_map_uses_datetimeutc() -> None:
16
- mapping = Base.type_annotation_map
17
- assert mapping[datetime] is DateTimeUTC
18
-
19
-
20
- def test_datetime_annotation_auto_uses_datetimeutc() -> None:
21
- """Verify that Mapped[datetime] automatically uses DateTimeUTC without explicit column type."""
22
-
23
- class TestModel(Base):
24
- __tablename__ = "test_auto_datetime"
25
- id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True, init=False)
26
- # No explicit DateTimeUTC type specified - should be inferred from type_annotation_map
27
- timestamp: Mapped[datetime]
28
-
29
- timestamp_column = TestModel.__table__.c.timestamp # type: ignore[attr-defined]
30
- assert isinstance(timestamp_column.type, DateTimeUTC)
31
-
32
-
33
- def test_naming_convention_applied() -> None:
34
- assert Base.metadata.naming_convention == NAMING_CONVENTION
35
-
36
-
37
- def test_dataclass_kw_only_init() -> None:
38
- user = User(email="a@b.com")
39
- assert user.email == "a@b.com"
40
-
41
-
42
- @pytest.mark.asyncio
43
- async def test_file_based_sqlite_database() -> None:
44
- """Test that models work correctly with file-based SQLite database."""
45
- with TemporaryDirectory() as tmpdir:
46
- db_path = Path(tmpdir) / "test.db"
47
- db_url = f"sqlite+aiosqlite:///{db_path}"
48
-
49
- # Create engine with file-based database
50
- engine = create_async_engine(db_url, echo=False)
51
-
52
- # Enable foreign keys for SQLite
53
- @event.listens_for(engine.sync_engine, "connect")
54
- def _enable_fk(dbapi_conn, _connection_record) -> None:
55
- cursor = dbapi_conn.cursor()
56
- cursor.execute("PRAGMA foreign_keys=ON")
57
- cursor.close()
58
-
59
- # Create tables
60
- async with engine.begin() as conn:
61
- await conn.run_sync(Base.metadata.create_all)
62
-
63
- # Create session factory
64
- session_factory = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
65
-
66
- # Test basic operations
67
- async with session_factory() as session:
68
- # Create user
69
- user = User(email="file_db_test@example.com", name="Test User")
70
- session.add(user)
71
- await session.commit()
72
-
73
- user_id = user.id
74
-
75
- # Verify persistence by reading in new session
76
- async with session_factory() as session:
77
- result = await session.execute(select(User).where(User.id == user_id))
78
- retrieved_user = result.scalar_one()
79
-
80
- assert retrieved_user.email == "file_db_test@example.com"
81
- assert retrieved_user.name == "Test User"
82
- assert retrieved_user.created_at is not None
83
- assert retrieved_user.created_at.tzinfo is UTC
84
-
85
- # Cleanup
86
- await engine.dispose()
87
-
88
- # Verify database file was created
89
- assert db_path.exists()
90
- assert db_path.stat().st_size > 0