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

rafalp / Misago / 17496798327

05 Sep 2025 02:59PM UTC coverage: 96.509% (-0.3%) from 96.769%
17496798327

Pull #1995

github

web-flow
Merge 17284d7d7 into 6bb938c90
Pull Request #1995: Move `Post` model from `misago.threads` to `misago.posts`

1884 of 1974 new or added lines in 149 files covered. (95.44%)

305 existing lines in 16 files now uncovered.

66716 of 69129 relevant lines covered (96.51%)

0.97 hits per line

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

36.11
/misago/threads/moderation/threads.py
1
from django.db import transaction
1✔
2
from django.utils import timezone
1✔
3

4
from ...notifications.tasks import delete_duplicate_watched_threads
1✔
5

6
__all__ = [
1✔
7
    "change_thread_title",
8
    "pin_thread_globally",
9
    "pin_thread_locally",
10
    "unpin_thread",
11
    "move_thread",
12
    "merge_thread",
13
    "approve_thread",
14
    "open_thread",
15
    "close_thread",
16
    "unhide_thread",
17
    "hide_thread",
18
    "delete_thread",
19
]
20

21

22
@transaction.atomic
1✔
23
def change_thread_title(request, thread, new_title):
1✔
UNCOV
24
    if thread.title == new_title:
×
25
        return False
×
26

UNCOV
27
    thread.set_title(new_title)
×
UNCOV
28
    thread.save(update_fields=["title", "slug"])
×
29

UNCOV
30
    thread.first_post.set_search_document(thread, "FIXME")
×
UNCOV
31
    thread.first_post.save(update_fields=["search_document"])
×
32

UNCOV
33
    thread.first_post.set_search_vector()
×
UNCOV
34
    thread.first_post.save(update_fields=["search_vector"])
×
35

UNCOV
36
    return True
×
37

38

39
@transaction.atomic
1✔
40
def pin_thread_globally(request, thread):
1✔
UNCOV
41
    if thread.weight == 2:
×
UNCOV
42
        return False
×
43

UNCOV
44
    thread.weight = 2
×
UNCOV
45
    thread.save(update_fields=["weight"])
×
46

UNCOV
47
    return True
×
48

49

50
@transaction.atomic
1✔
51
def pin_thread_locally(request, thread):
1✔
UNCOV
52
    if thread.weight == 1:
×
UNCOV
53
        return False
×
54

UNCOV
55
    thread.weight = 1
×
UNCOV
56
    thread.save(update_fields=["weight"])
×
57

UNCOV
58
    return True
×
59

60

61
@transaction.atomic
1✔
62
def unpin_thread(request, thread):
1✔
UNCOV
63
    if thread.weight == 0:
×
UNCOV
64
        return False
×
65

UNCOV
66
    thread.weight = 0
×
UNCOV
67
    thread.save(update_fields=["weight"])
×
68

UNCOV
69
    return True
×
70

71

72
@transaction.atomic
1✔
73
def move_thread(request, thread, new_category):
1✔
UNCOV
74
    if thread.category_id == new_category.pk:
×
UNCOV
75
        return False
×
76

UNCOV
77
    thread.move(new_category)
×
UNCOV
78
    thread.save()
×
79

UNCOV
80
    return True
×
81

82

83
@transaction.atomic
1✔
84
def merge_thread(request, thread, other_thread):
1✔
85
    thread.merge(other_thread)
×
86
    other_thread.delete()
×
87

88
    delete_duplicate_watched_threads.delay(thread.id)
×
89
    return True
×
90

91

92
@transaction.atomic
1✔
93
def approve_thread(request, thread):
1✔
UNCOV
94
    if not thread.is_unapproved:
×
95
        return False
×
96

UNCOV
97
    thread.first_post.is_unapproved = False
×
UNCOV
98
    thread.first_post.save(update_fields=["is_unapproved"])
×
99

UNCOV
100
    thread.is_unapproved = False
×
101

UNCOV
102
    unapproved_post_qs = thread.post_set.filter(is_unapproved=True)
×
UNCOV
103
    thread.has_unapproved_posts = unapproved_post_qs.exists()
×
UNCOV
104
    thread.save(update_fields=["is_unapproved", "has_unapproved_posts"])
×
105

UNCOV
106
    return True
×
107

108

109
@transaction.atomic
1✔
110
def open_thread(request, thread):
1✔
UNCOV
111
    if not thread.is_closed:
×
UNCOV
112
        return False
×
113

UNCOV
114
    thread.is_closed = False
×
UNCOV
115
    thread.save(update_fields=["is_closed"])
×
116

UNCOV
117
    return True
×
118

119

120
@transaction.atomic
1✔
121
def close_thread(request, thread):
1✔
UNCOV
122
    if thread.is_closed:
×
UNCOV
123
        return False
×
124

UNCOV
125
    thread.is_closed = True
×
UNCOV
126
    thread.save(update_fields=["is_closed"])
×
127

UNCOV
128
    return True
×
129

130

131
@transaction.atomic
1✔
132
def unhide_thread(request, thread):
1✔
UNCOV
133
    if not thread.is_hidden:
×
UNCOV
134
        return False
×
135

UNCOV
136
    thread.first_post.is_hidden = False
×
UNCOV
137
    thread.first_post.save(update_fields=["is_hidden"])
×
UNCOV
138
    thread.is_hidden = False
×
UNCOV
139
    thread.save(update_fields=["is_hidden"])
×
140

UNCOV
141
    if thread.pk == thread.category.last_thread_id:
×
142
        thread.category.synchronize()
×
143
        thread.category.save()
×
144

UNCOV
145
    return True
×
146

147

148
@transaction.atomic
1✔
149
def hide_thread(request, thread):
1✔
150
    if thread.is_hidden:
1✔
UNCOV
151
        return False
×
152

153
    thread.first_post.is_hidden = True
1✔
154
    thread.first_post.hidden_by = request.user
1✔
155
    thread.first_post.hidden_by_name = request.user.username
1✔
156
    thread.first_post.hidden_by_slug = request.user.slug
1✔
157
    thread.first_post.hidden_at = timezone.now()
1✔
158
    thread.first_post.save(
1✔
159
        update_fields=[
160
            "is_hidden",
161
            "hidden_by",
162
            "hidden_by_name",
163
            "hidden_by_slug",
164
            "hidden_at",
165
        ]
166
    )
167
    thread.is_hidden = True
1✔
168
    thread.save(update_fields=["is_hidden"])
1✔
169

170
    if thread.pk == thread.category.last_thread_id:
1✔
UNCOV
171
        thread.category.synchronize()
×
UNCOV
172
        thread.category.save()
×
173

174
    return True
1✔
175

176

177
@transaction.atomic
1✔
178
def delete_thread(request, thread):
1✔
UNCOV
179
    thread.delete()
×
180

UNCOV
181
    thread.category.synchronize()
×
UNCOV
182
    thread.category.save()
×
183

UNCOV
184
    return True
×
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