• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

rafalp / Misago / 15760443583

19 Jun 2025 02:37PM UTC coverage: 97.274% (+0.06%) from 97.214%
15760443583

push

github

web-flow
Replace thread events with updates (#1944)

2828 of 2914 new or added lines in 89 files covered. (97.05%)

27 existing lines in 5 files now uncovered.

74115 of 76192 relevant lines covered (97.27%)

0.97 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.0
/misago/threads/hooks/create_prefetch_posts_feed_related_objects.py
1
from typing import TYPE_CHECKING, Iterable, Protocol
1✔
2

3
from ...attachments.models import Attachment
1✔
4
from ...categories.models import Category
1✔
5
from ...conf.dynamicsettings import DynamicSettings
1✔
6
from ...permissions.proxy import UserPermissionsProxy
1✔
7
from ...plugins.hooks import FilterHook
1✔
8
from ...threadupdates.models import ThreadUpdate
1✔
9
from ..models import Post, Thread
1✔
10

11
if TYPE_CHECKING:
1✔
12
    from ...users.models import User
×
NEW
13
    from ..prefetch import PrefetchPostsFeedRelatedObjects
×
14

15

16
class CreatePrefetchPostsFeedRelatedObjectsHookAction(Protocol):
1✔
17
    """
18
    A standard Misago function used to create a `PrefetchPostsFeedRelatedObjects`
19
    object, which is used to prefetch related objects for items displayed on
20
    a posts feed.
21

22
    # Arguments
23

24
    ## `settings: DynamicSettings`
25

26
    The `DynamicSettings` object.
27

28
    ## `permissions: UserPermissionsProxy`
29

30
    The `UserPermissionsProxy` object for current user.
31

32
    ## `posts: Iterable[Post]`
33

34
    Iterable of `Post` instances to prefetch related objects for.
35

36
    ## `categories: Iterable[Category] | None = None`
37

38
    Iterable of categories that were already loaded. Defaults to `None` if not
39
    provided.
40

41
    ## `threads: Iterable[Thread] | None = None`
42

43
    Iterable of threads that were already loaded. Defaults to `None` if not provided.
44

45
    ## `thread_updates: Iterable[ThreadUpdate] | None = None,`
46

47
    Iterable of `ThreadUpdate` instances to prefetch related objects for.
48
    Defaults to `None` if not provided.
49

50
    ## `attachments: Iterable[Attachment] | None = None`
51

52
    Iterable of attachments that were already loaded. Defaults to `None` if not
53
    provided.
54

55
    ## `users: Iterable["User"] | None = None`
56

57
    Iterable of users that were already loaded. Defaults to `None` if not provided.
58

59
    # Return value
60

61
    A `PrefetchPostsFeedRelatedObjects` object to use to fetch related objects.
62
    """
63

64
    def __call__(
1✔
65
        self,
66
        settings: DynamicSettings,
67
        permissions: UserPermissionsProxy,
68
        posts: Iterable[Post],
69
        *,
70
        categories: Iterable[Category] | None = None,
71
        threads: Iterable[Thread] | None = None,
72
        thread_updates: Iterable[ThreadUpdate] | None = None,
73
        attachments: Iterable[Attachment] | None = None,
74
        users: Iterable["User"] | None = None,
75
    ) -> "PrefetchPostsFeedRelatedObjects": ...
76

77

78
class CreatePrefetchPostsFeedRelatedObjectsHookFilter(Protocol):
1✔
79
    """
80
    A function implemented by a plugin that can be registered in this hook.
81

82
    # Arguments
83

84
    ## `action: CreatePrefetchPostsFeedRelatedObjectsHookAction`
85

86
    A standard Misago function used to create a `PrefetchPostsFeedRelatedObjects`
87
    object, which is used to prefetch related objects for items displayed on
88
    a posts feed.
89

90
    See the [action](#action) section for details.
91

92
    ## `settings: DynamicSettings`
93

94
    The `DynamicSettings` object.
95

96
    ## `permissions: UserPermissionsProxy`
97

98
    The `UserPermissionsProxy` object for current user.
99

100
    ## `posts: Iterable[Post]`
101

102
    Iterable of `Post` instances to prefetch related objects for.
103

104
    ## `categories: Iterable[Category] | None = None`
105

106
    Iterable of categories that were already loaded. Defaults to `None` if not
107
    provided.
108

109
    ## `threads: Iterable[Thread] | None = None`
110

111
    Iterable of threads that were already loaded. Defaults to `None` if not provided.
112

113
    ## `thread_updates: Iterable[ThreadUpdate] | None = None,`
114

115
    Iterable of `ThreadUpdate` instances to prefetch related objects for.
116
    Defaults to `None` if not provided.
117

118
    ## `attachments: Iterable[Attachment] | None = None`
119

120
    Iterable of attachments that were already loaded. Defaults to `None` if not
121
    provided.
122

123
    ## `users: Iterable["User"] | None = None`
124

125
    Iterable of users that were already loaded. Defaults to `None` if not provided.
126

127
    # Return value
128

129
    A `PrefetchPostsFeedRelatedObjects` object to use to fetch related objects.
130
    """
131

132
    def __call__(
1✔
133
        self,
134
        action: CreatePrefetchPostsFeedRelatedObjectsHookAction,
135
        settings: DynamicSettings,
136
        permissions: UserPermissionsProxy,
137
        posts: Iterable[Post],
138
        *,
139
        categories: Iterable[Category] | None = None,
140
        threads: Iterable[Thread] | None = None,
141
        thread_updates: Iterable[ThreadUpdate] | None = None,
142
        attachments: Iterable[Attachment] | None = None,
143
        users: Iterable["User"] | None = None,
144
    ) -> "PrefetchPostsFeedRelatedObjects": ...
145

146

147
class CreatePrefetchPostsFeedRelatedObjectsHook(
1✔
148
    FilterHook[
149
        CreatePrefetchPostsFeedRelatedObjectsHookAction,
150
        CreatePrefetchPostsFeedRelatedObjectsHookFilter,
151
    ]
152
):
153
    """
154
    This hook wraps the standard function Misago uses to create a
155
    `PrefetchPostsFeedRelatedObjects` object, which is used to prefetch related
156
    objects for items displayed in a posts feed.
157

158
    The object itself does not implement prefetch logic but instead maintains
159
    a list of prefetch operations to be executed in order to fetch the objects
160
    from the database.
161

162
    Additional prefetch operations can be added using the `add`, `add_after`
163
    and `add_before` methods.
164

165
    # Example
166

167
    The code below implements a custom filter function that includes a new
168
    prefetch operation:
169

170
    ```python
171
    from typing import Iterable
172

173
    from misago.attachments.models import Attachment
174
    from misago.categories.models import Category
175
    from misago.conf.dynamicsettings import DynamicSettings
176
    from misago.permissions.proxy import UserPermissionsProxy
177
    from misago.plugins.hooks import FilterHook
178
    from misago.threads.models import Post, Thread, ThreadUpdate
179
    from misago.threads.prefetch import PrefetchPostsFeedRelatedObjects
180
    from misago.users.models import User
181

182
    from .plugin.models import PluginModel
183

184

185
    def fetch_posts_plugin_data(
186
        data: dict,
187
        settings: DynamicSettings,
188
        permissions: UserPermissionsProxy,
189
    ):
190
        data["plugin_models"] = {}
191
        ids_to_fetch: set[int] = set()
192

193
        for post in data["posts"].values():
194
            ids_to_fetch.add(post.plugin_data["plugin_object_id"])
195

196
        if ids_to_fetch:
197
            queryset = PluginModel.objects.filter(id__in=ids_to_fetch)
198
            data["plugin_models"] = {u.id: u for u in queryset}
199

200

201
    @create_prefetch_posts_feed_related_objects_hook.append_filter
202
    def include_custom_filter(
203
        action: CreatePrefetchPostsFeedRelatedObjectsHookAction,
204
        settings: DynamicSettings,
205
        permissions: UserPermissionsProxy,
206
        posts: Iterable[Post],
207
        *,
208
        categories: Iterable[Category] | None = None,
209
        threads: Iterable[Thread] | None = None,
210
        thread_updates: Iterable[ThreadUpdate] | None = None,
211
        attachments: Iterable[Attachment] | None = None,
212
        users: Iterable["User"] | None = None,
213
    ) -> PrefetchPostsFeedRelatedObjects:
214
        prefetch = action(
215
            settings,
216
            permissions,
217
            posts,
218
            categories=categories,
219
            threads=threads,
220
            thread_updates=thread_updates,
221
            attachments=attachments,
222
            users=users,
223
        )
224

225
        prefetch.add_operation(fetch_posts_plugin_data)
226

227
        return prefetch
228
    ```
229
    """
230

231
    __slots__ = FilterHook.__slots__
1✔
232

233
    def __call__(
1✔
234
        self,
235
        action: CreatePrefetchPostsFeedRelatedObjectsHookAction,
236
        settings: DynamicSettings,
237
        permissions: UserPermissionsProxy,
238
        posts: Iterable[Post],
239
        *,
240
        categories: Iterable[Category] | None = None,
241
        threads: Iterable[Thread] | None = None,
242
        thread_updates: Iterable[ThreadUpdate] | None = None,
243
        attachments: Iterable[Attachment] | None = None,
244
        users: Iterable["User"] | None = None,
245
    ) -> "PrefetchPostsFeedRelatedObjects":
246
        return super().__call__(
1✔
247
            action,
248
            settings,
249
            permissions,
250
            posts,
251
            categories=categories,
252
            threads=threads,
253
            thread_updates=thread_updates,
254
            attachments=attachments,
255
            users=users,
256
        )
257

258

259
create_prefetch_posts_feed_related_objects_hook = (
1✔
260
    CreatePrefetchPostsFeedRelatedObjectsHook(cache=False)
261
)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc