fastapi-plugin-notification 0.2.0__tar.gz → 0.2.1__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.
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/PKG-INFO +5 -1
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/README.md +4 -0
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/fastapi_plugin_notification/__init__.py +1 -1
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/fastapi_plugin_notification/client.py +56 -0
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/fastapi_plugin_notification.egg-info/PKG-INFO +5 -1
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/pyproject.toml +1 -1
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/tests/test_client.py +202 -0
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/LICENSE +0 -0
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/fastapi_plugin_notification/app.py +0 -0
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/fastapi_plugin_notification/controller.py +0 -0
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/fastapi_plugin_notification/models.py +0 -0
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/fastapi_plugin_notification/schemas.py +0 -0
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/fastapi_plugin_notification/types.py +0 -0
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/fastapi_plugin_notification.egg-info/SOURCES.txt +0 -0
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/fastapi_plugin_notification.egg-info/dependency_links.txt +0 -0
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/fastapi_plugin_notification.egg-info/requires.txt +0 -0
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/fastapi_plugin_notification.egg-info/top_level.txt +0 -0
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/setup.cfg +0 -0
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/tests/test_app.py +0 -0
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/tests/test_controller.py +0 -0
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/tests/test_models.py +0 -0
- {fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/tests/test_schemas.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastapi-plugin-notification
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Notification plugin for FastAPI projects using FastAPI SDK and Postmark provider.
|
|
5
5
|
Requires-Python: >=3.12
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -30,6 +30,7 @@ A notification plugin for FastAPI that integrates with FastAPI SDK and Postmark
|
|
|
30
30
|
- Mark notifications as seen/acknowledged
|
|
31
31
|
- Get unseen notification count
|
|
32
32
|
- 🗞️ **Digests**: Daily or weekly digest emails, grouped by category
|
|
33
|
+
- 🧹 **Retention**: Configurable cleanup of notifications past their retention window
|
|
33
34
|
- 🚀 **FastAPI Integration**: Full CRUD API endpoints with authentication
|
|
34
35
|
- 📦 **PyPI Package**: Easy to install and use in any FastAPI project
|
|
35
36
|
|
|
@@ -78,12 +79,15 @@ Full setup — client, router and dependencies — is in the [Quick Start](docs/
|
|
|
78
79
|
| [Quick Start](docs/quickstart.md) | Initialize the client, mount the router, send your first notification |
|
|
79
80
|
| [Usage Examples](docs/usage.md) | Storing, sending, listing and acknowledging notifications |
|
|
80
81
|
| [Notification Digests](docs/digests.md) | Daily/weekly digests, category grouping, example payload, Postmark Mustachio templates |
|
|
82
|
+
| [Cleaning Up Old Notifications](docs/cleanup.md) | Retention window and permanently removing stale notifications |
|
|
81
83
|
| [API Endpoints](docs/api-endpoints.md) | HTTP routes with request parameters and response bodies |
|
|
82
84
|
| [Model Structure](docs/model.md) | Fields on `NotificationModel` |
|
|
83
85
|
| [Ownership and Permissions](docs/ownership.md) | Claim-based ownership and required permissions |
|
|
84
86
|
| [Configuration](docs/configuration.md) | Router options, template variables, error handling |
|
|
85
87
|
| [Development](docs/development.md) | Local setup and running the tests |
|
|
86
88
|
|
|
89
|
+
Release history is in the [Changelog](CHANGELOG.md).
|
|
90
|
+
|
|
87
91
|
## License
|
|
88
92
|
|
|
89
93
|
MIT License - see LICENSE file for details
|
|
@@ -12,6 +12,7 @@ A notification plugin for FastAPI that integrates with FastAPI SDK and Postmark
|
|
|
12
12
|
- Mark notifications as seen/acknowledged
|
|
13
13
|
- Get unseen notification count
|
|
14
14
|
- 🗞️ **Digests**: Daily or weekly digest emails, grouped by category
|
|
15
|
+
- 🧹 **Retention**: Configurable cleanup of notifications past their retention window
|
|
15
16
|
- 🚀 **FastAPI Integration**: Full CRUD API endpoints with authentication
|
|
16
17
|
- 📦 **PyPI Package**: Easy to install and use in any FastAPI project
|
|
17
18
|
|
|
@@ -60,12 +61,15 @@ Full setup — client, router and dependencies — is in the [Quick Start](docs/
|
|
|
60
61
|
| [Quick Start](docs/quickstart.md) | Initialize the client, mount the router, send your first notification |
|
|
61
62
|
| [Usage Examples](docs/usage.md) | Storing, sending, listing and acknowledging notifications |
|
|
62
63
|
| [Notification Digests](docs/digests.md) | Daily/weekly digests, category grouping, example payload, Postmark Mustachio templates |
|
|
64
|
+
| [Cleaning Up Old Notifications](docs/cleanup.md) | Retention window and permanently removing stale notifications |
|
|
63
65
|
| [API Endpoints](docs/api-endpoints.md) | HTTP routes with request parameters and response bodies |
|
|
64
66
|
| [Model Structure](docs/model.md) | Fields on `NotificationModel` |
|
|
65
67
|
| [Ownership and Permissions](docs/ownership.md) | Claim-based ownership and required permissions |
|
|
66
68
|
| [Configuration](docs/configuration.md) | Router options, template variables, error handling |
|
|
67
69
|
| [Development](docs/development.md) | Local setup and running the tests |
|
|
68
70
|
|
|
71
|
+
Release history is in the [Changelog](CHANGELOG.md).
|
|
72
|
+
|
|
69
73
|
## License
|
|
70
74
|
|
|
71
75
|
MIT License - see LICENSE file for details
|
|
@@ -18,6 +18,8 @@ _DIGEST_PERIOD_DELTAS = {
|
|
|
18
18
|
DigestPeriod.WEEK: timedelta(days=7),
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
DEFAULT_RETENTION_DAYS = 30
|
|
22
|
+
|
|
21
23
|
|
|
22
24
|
class NotificationClient:
|
|
23
25
|
"""Client for storing and optionally sending notifications."""
|
|
@@ -28,6 +30,7 @@ class NotificationClient:
|
|
|
28
30
|
default_template_id: Optional[int] = None,
|
|
29
31
|
default_digest_template_id: Optional[int] = None,
|
|
30
32
|
digest_template_ids: Optional[Dict[str, int]] = None,
|
|
33
|
+
retention_days: int = DEFAULT_RETENTION_DAYS,
|
|
31
34
|
):
|
|
32
35
|
"""Initialize the notification client.
|
|
33
36
|
|
|
@@ -36,11 +39,14 @@ class NotificationClient:
|
|
|
36
39
|
default_template_id: Default Postmark template ID to use for emails
|
|
37
40
|
default_digest_template_id: Default Postmark template ID for digests
|
|
38
41
|
digest_template_ids: Per-period digest template IDs (keys: day, week)
|
|
42
|
+
retention_days: Age in days after which notifications become eligible
|
|
43
|
+
for cleanup (default: 30)
|
|
39
44
|
"""
|
|
40
45
|
self.postmark_provider = postmark_provider
|
|
41
46
|
self.default_template_id = default_template_id
|
|
42
47
|
self.default_digest_template_id = default_digest_template_id
|
|
43
48
|
self.digest_template_ids = digest_template_ids or {}
|
|
49
|
+
self.retention_days = retention_days
|
|
44
50
|
|
|
45
51
|
async def store_notification(
|
|
46
52
|
self,
|
|
@@ -543,3 +549,53 @@ class NotificationClient:
|
|
|
543
549
|
claims=claims,
|
|
544
550
|
)
|
|
545
551
|
return result
|
|
552
|
+
|
|
553
|
+
async def cleanup_old_notifications(
|
|
554
|
+
self,
|
|
555
|
+
db_engine: AIOEngine,
|
|
556
|
+
retention_days: Optional[int] = None,
|
|
557
|
+
include_unseen: bool = False,
|
|
558
|
+
dry_run: bool = False,
|
|
559
|
+
) -> int:
|
|
560
|
+
"""Permanently remove notifications older than the retention window.
|
|
561
|
+
|
|
562
|
+
Unlike the controller's soft delete, this removes documents from the
|
|
563
|
+
database so the collection does not grow indefinitely. Unseen
|
|
564
|
+
notifications are preserved unless ``include_unseen`` is set, while
|
|
565
|
+
soft deleted notifications are always purged once old enough.
|
|
566
|
+
|
|
567
|
+
Args:
|
|
568
|
+
db_engine: MongoDB engine instance from odmantic
|
|
569
|
+
retention_days: Age in days to keep (defaults to the client's
|
|
570
|
+
``retention_days``)
|
|
571
|
+
include_unseen: Also remove notifications the user has not seen
|
|
572
|
+
dry_run: Count the matching notifications without deleting them
|
|
573
|
+
|
|
574
|
+
Returns:
|
|
575
|
+
Number of notifications deleted, or that would be deleted for a dry run
|
|
576
|
+
"""
|
|
577
|
+
days = self.retention_days if retention_days is None else retention_days
|
|
578
|
+
cutoff = datetime.now(timezone.utc).replace(tzinfo=None) - timedelta(days=days)
|
|
579
|
+
|
|
580
|
+
query: Dict[str, Any] = {"created_at": {"$lt": cutoff}}
|
|
581
|
+
if not include_unseen:
|
|
582
|
+
query["$or"] = [{"seen": True}, {"deleted": True}]
|
|
583
|
+
|
|
584
|
+
collection = db_engine.database[NotificationModel.__collection__]
|
|
585
|
+
|
|
586
|
+
if dry_run:
|
|
587
|
+
count = await collection.count_documents(query)
|
|
588
|
+
logger.info(
|
|
589
|
+
"Cleanup dry run: %s notifications older than %s days would be deleted",
|
|
590
|
+
count,
|
|
591
|
+
days,
|
|
592
|
+
)
|
|
593
|
+
return count
|
|
594
|
+
|
|
595
|
+
result = await collection.delete_many(query)
|
|
596
|
+
logger.info(
|
|
597
|
+
"Deleted %s notifications older than %s days",
|
|
598
|
+
result.deleted_count,
|
|
599
|
+
days,
|
|
600
|
+
)
|
|
601
|
+
return result.deleted_count
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastapi-plugin-notification
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Notification plugin for FastAPI projects using FastAPI SDK and Postmark provider.
|
|
5
5
|
Requires-Python: >=3.12
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -30,6 +30,7 @@ A notification plugin for FastAPI that integrates with FastAPI SDK and Postmark
|
|
|
30
30
|
- Mark notifications as seen/acknowledged
|
|
31
31
|
- Get unseen notification count
|
|
32
32
|
- 🗞️ **Digests**: Daily or weekly digest emails, grouped by category
|
|
33
|
+
- 🧹 **Retention**: Configurable cleanup of notifications past their retention window
|
|
33
34
|
- 🚀 **FastAPI Integration**: Full CRUD API endpoints with authentication
|
|
34
35
|
- 📦 **PyPI Package**: Easy to install and use in any FastAPI project
|
|
35
36
|
|
|
@@ -78,12 +79,15 @@ Full setup — client, router and dependencies — is in the [Quick Start](docs/
|
|
|
78
79
|
| [Quick Start](docs/quickstart.md) | Initialize the client, mount the router, send your first notification |
|
|
79
80
|
| [Usage Examples](docs/usage.md) | Storing, sending, listing and acknowledging notifications |
|
|
80
81
|
| [Notification Digests](docs/digests.md) | Daily/weekly digests, category grouping, example payload, Postmark Mustachio templates |
|
|
82
|
+
| [Cleaning Up Old Notifications](docs/cleanup.md) | Retention window and permanently removing stale notifications |
|
|
81
83
|
| [API Endpoints](docs/api-endpoints.md) | HTTP routes with request parameters and response bodies |
|
|
82
84
|
| [Model Structure](docs/model.md) | Fields on `NotificationModel` |
|
|
83
85
|
| [Ownership and Permissions](docs/ownership.md) | Claim-based ownership and required permissions |
|
|
84
86
|
| [Configuration](docs/configuration.md) | Router options, template variables, error handling |
|
|
85
87
|
| [Development](docs/development.md) | Local setup and running the tests |
|
|
86
88
|
|
|
89
|
+
Release history is in the [Changelog](CHANGELOG.md).
|
|
90
|
+
|
|
87
91
|
## License
|
|
88
92
|
|
|
89
93
|
MIT License - see LICENSE file for details
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "fastapi-plugin-notification"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.1"
|
|
8
8
|
description = "Notification plugin for FastAPI projects using FastAPI SDK and Postmark provider."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
{fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/tests/test_client.py
RENAMED
|
@@ -722,3 +722,205 @@ class TestSendNotificationDigest:
|
|
|
722
722
|
|
|
723
723
|
assert digest["count"] == 1
|
|
724
724
|
assert digest["email_sent"] is False
|
|
725
|
+
|
|
726
|
+
|
|
727
|
+
class TestCleanupOldNotifications:
|
|
728
|
+
"""Tests for cleanup_old_notifications method."""
|
|
729
|
+
|
|
730
|
+
async def _create_notification_at(
|
|
731
|
+
self,
|
|
732
|
+
notification_client,
|
|
733
|
+
db_engine,
|
|
734
|
+
mock_claims,
|
|
735
|
+
name: str,
|
|
736
|
+
created_at: datetime,
|
|
737
|
+
seen: bool = False,
|
|
738
|
+
deleted: bool = False,
|
|
739
|
+
) -> NotificationModel:
|
|
740
|
+
notification = await notification_client.store_notification(
|
|
741
|
+
db_engine=db_engine,
|
|
742
|
+
name=name,
|
|
743
|
+
user_id="user_123",
|
|
744
|
+
user_email="user@example.com",
|
|
745
|
+
claims=mock_claims,
|
|
746
|
+
)
|
|
747
|
+
notification.created_at = created_at
|
|
748
|
+
notification.updated_at = created_at
|
|
749
|
+
notification.seen = seen
|
|
750
|
+
notification.deleted = deleted
|
|
751
|
+
await db_engine.save(notification)
|
|
752
|
+
return notification
|
|
753
|
+
|
|
754
|
+
async def _remaining_names(self, db_engine) -> set:
|
|
755
|
+
collection = db_engine.database["notification"]
|
|
756
|
+
return {doc["name"] async for doc in collection.find({})}
|
|
757
|
+
|
|
758
|
+
def test_default_retention_is_thirty_days(self, notification_client):
|
|
759
|
+
"""Test the client defaults to a 30 day retention window."""
|
|
760
|
+
assert notification_client.retention_days == 30
|
|
761
|
+
|
|
762
|
+
def test_retention_days_configurable_on_init(self, postmark_provider):
|
|
763
|
+
"""Test the retention window can be overridden when instantiating."""
|
|
764
|
+
client = NotificationClient(
|
|
765
|
+
postmark_provider=postmark_provider,
|
|
766
|
+
retention_days=90,
|
|
767
|
+
)
|
|
768
|
+
assert client.retention_days == 90
|
|
769
|
+
|
|
770
|
+
@pytest.mark.asyncio
|
|
771
|
+
async def test_cleanup_removes_old_seen_notifications(
|
|
772
|
+
self, notification_client, db_engine, mock_claims
|
|
773
|
+
):
|
|
774
|
+
"""Test old seen notifications are hard deleted."""
|
|
775
|
+
now = datetime.now(timezone.utc).replace(tzinfo=None)
|
|
776
|
+
|
|
777
|
+
await self._create_notification_at(
|
|
778
|
+
notification_client,
|
|
779
|
+
db_engine,
|
|
780
|
+
mock_claims,
|
|
781
|
+
"old_seen",
|
|
782
|
+
now - timedelta(days=31),
|
|
783
|
+
seen=True,
|
|
784
|
+
)
|
|
785
|
+
await self._create_notification_at(
|
|
786
|
+
notification_client,
|
|
787
|
+
db_engine,
|
|
788
|
+
mock_claims,
|
|
789
|
+
"recent_seen",
|
|
790
|
+
now - timedelta(days=2),
|
|
791
|
+
seen=True,
|
|
792
|
+
)
|
|
793
|
+
|
|
794
|
+
deleted = await notification_client.cleanup_old_notifications(
|
|
795
|
+
db_engine=db_engine
|
|
796
|
+
)
|
|
797
|
+
|
|
798
|
+
assert deleted == 1
|
|
799
|
+
assert await self._remaining_names(db_engine) == {"recent_seen"}
|
|
800
|
+
|
|
801
|
+
@pytest.mark.asyncio
|
|
802
|
+
async def test_cleanup_preserves_old_unseen_notifications(
|
|
803
|
+
self, notification_client, db_engine, mock_claims
|
|
804
|
+
):
|
|
805
|
+
"""Test unseen notifications survive cleanup by default."""
|
|
806
|
+
now = datetime.now(timezone.utc).replace(tzinfo=None)
|
|
807
|
+
|
|
808
|
+
await self._create_notification_at(
|
|
809
|
+
notification_client,
|
|
810
|
+
db_engine,
|
|
811
|
+
mock_claims,
|
|
812
|
+
"old_unseen",
|
|
813
|
+
now - timedelta(days=60),
|
|
814
|
+
seen=False,
|
|
815
|
+
)
|
|
816
|
+
|
|
817
|
+
deleted = await notification_client.cleanup_old_notifications(
|
|
818
|
+
db_engine=db_engine
|
|
819
|
+
)
|
|
820
|
+
|
|
821
|
+
assert deleted == 0
|
|
822
|
+
assert await self._remaining_names(db_engine) == {"old_unseen"}
|
|
823
|
+
|
|
824
|
+
@pytest.mark.asyncio
|
|
825
|
+
async def test_cleanup_removes_old_unseen_when_included(
|
|
826
|
+
self, notification_client, db_engine, mock_claims
|
|
827
|
+
):
|
|
828
|
+
"""Test include_unseen also removes old unread notifications."""
|
|
829
|
+
now = datetime.now(timezone.utc).replace(tzinfo=None)
|
|
830
|
+
|
|
831
|
+
await self._create_notification_at(
|
|
832
|
+
notification_client,
|
|
833
|
+
db_engine,
|
|
834
|
+
mock_claims,
|
|
835
|
+
"old_unseen",
|
|
836
|
+
now - timedelta(days=60),
|
|
837
|
+
seen=False,
|
|
838
|
+
)
|
|
839
|
+
await self._create_notification_at(
|
|
840
|
+
notification_client,
|
|
841
|
+
db_engine,
|
|
842
|
+
mock_claims,
|
|
843
|
+
"recent_unseen",
|
|
844
|
+
now - timedelta(days=1),
|
|
845
|
+
seen=False,
|
|
846
|
+
)
|
|
847
|
+
|
|
848
|
+
deleted = await notification_client.cleanup_old_notifications(
|
|
849
|
+
db_engine=db_engine,
|
|
850
|
+
include_unseen=True,
|
|
851
|
+
)
|
|
852
|
+
|
|
853
|
+
assert deleted == 1
|
|
854
|
+
assert await self._remaining_names(db_engine) == {"recent_unseen"}
|
|
855
|
+
|
|
856
|
+
@pytest.mark.asyncio
|
|
857
|
+
async def test_cleanup_purges_old_soft_deleted_notifications(
|
|
858
|
+
self, notification_client, db_engine, mock_claims
|
|
859
|
+
):
|
|
860
|
+
"""Test soft deleted notifications are purged even when unseen."""
|
|
861
|
+
now = datetime.now(timezone.utc).replace(tzinfo=None)
|
|
862
|
+
|
|
863
|
+
await self._create_notification_at(
|
|
864
|
+
notification_client,
|
|
865
|
+
db_engine,
|
|
866
|
+
mock_claims,
|
|
867
|
+
"old_soft_deleted",
|
|
868
|
+
now - timedelta(days=45),
|
|
869
|
+
seen=False,
|
|
870
|
+
deleted=True,
|
|
871
|
+
)
|
|
872
|
+
|
|
873
|
+
deleted = await notification_client.cleanup_old_notifications(
|
|
874
|
+
db_engine=db_engine
|
|
875
|
+
)
|
|
876
|
+
|
|
877
|
+
assert deleted == 1
|
|
878
|
+
assert await self._remaining_names(db_engine) == set()
|
|
879
|
+
|
|
880
|
+
@pytest.mark.asyncio
|
|
881
|
+
async def test_cleanup_respects_per_call_retention_days(
|
|
882
|
+
self, notification_client, db_engine, mock_claims
|
|
883
|
+
):
|
|
884
|
+
"""Test retention_days argument overrides the client default."""
|
|
885
|
+
now = datetime.now(timezone.utc).replace(tzinfo=None)
|
|
886
|
+
|
|
887
|
+
await self._create_notification_at(
|
|
888
|
+
notification_client,
|
|
889
|
+
db_engine,
|
|
890
|
+
mock_claims,
|
|
891
|
+
"ten_days_old",
|
|
892
|
+
now - timedelta(days=10),
|
|
893
|
+
seen=True,
|
|
894
|
+
)
|
|
895
|
+
|
|
896
|
+
deleted = await notification_client.cleanup_old_notifications(
|
|
897
|
+
db_engine=db_engine,
|
|
898
|
+
retention_days=7,
|
|
899
|
+
)
|
|
900
|
+
|
|
901
|
+
assert deleted == 1
|
|
902
|
+
assert await self._remaining_names(db_engine) == set()
|
|
903
|
+
|
|
904
|
+
@pytest.mark.asyncio
|
|
905
|
+
async def test_cleanup_dry_run_reports_without_deleting(
|
|
906
|
+
self, notification_client, db_engine, mock_claims
|
|
907
|
+
):
|
|
908
|
+
"""Test dry_run returns the count without removing anything."""
|
|
909
|
+
now = datetime.now(timezone.utc).replace(tzinfo=None)
|
|
910
|
+
|
|
911
|
+
await self._create_notification_at(
|
|
912
|
+
notification_client,
|
|
913
|
+
db_engine,
|
|
914
|
+
mock_claims,
|
|
915
|
+
"old_seen",
|
|
916
|
+
now - timedelta(days=31),
|
|
917
|
+
seen=True,
|
|
918
|
+
)
|
|
919
|
+
|
|
920
|
+
deleted = await notification_client.cleanup_old_notifications(
|
|
921
|
+
db_engine=db_engine,
|
|
922
|
+
dry_run=True,
|
|
923
|
+
)
|
|
924
|
+
|
|
925
|
+
assert deleted == 1
|
|
926
|
+
assert await self._remaining_names(db_engine) == {"old_seen"}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/tests/test_controller.py
RENAMED
|
File without changes
|
{fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/tests/test_models.py
RENAMED
|
File without changes
|
{fastapi_plugin_notification-0.2.0 → fastapi_plugin_notification-0.2.1}/tests/test_schemas.py
RENAMED
|
File without changes
|