Skip to content

Commit f97325e

Browse files
polkertyJelteF
andcommittedFeb 16, 2025
Add dummy data for development (#5)
This PR implements a way to use dummy data for development in two ways: 1. Dump a working dev database with Django's `dumpdata` command. We dump the `auth` and `commitfest` modules separately. This data can likewise be reloaded when starting from scratch with the corresponding `loaddata` commands (see the README.) 2. Mocks the archives server, to allow users to search and add sample mailing threads to their patches. To avoid an infinite recursion error this change also required moving the ManyToMany relationship between MailThread and Patch from the MailThread to Patch side. --------- Co-authored-by: Jelte Fennema-Nio <[email protected]>
1 parent f7f40ff commit f97325e

File tree

9 files changed

+1075
-3
lines changed

9 files changed

+1075
-3
lines changed
 

‎README.md

+23-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ This is a Django 4.2 application backed by PostgreSQL and running on Python 3.x.
1212

1313
### Ubuntu instructions
1414

15+
#### Install Dependencies / Configure Environment
16+
1517
First, prepare your development environment by installing pip, virtualenv, and postgresql-server-dev-X.Y.
1618

1719
```bash
@@ -45,12 +47,24 @@ be provided.
4547
./manage.py migrate
4648
```
4749

48-
You'll need either a database dump of the actual server's data or else to create a superuser:
50+
#### Load data
51+
For a quick start, you can load some dummy data into the database. Here's how you do that:
52+
53+
```
54+
./manage.py loaddata auth_data.json
55+
./manage.py loaddata commitfest_data.json
56+
```
57+
58+
If you do this, the admin username and password are `admin` and `admin`.
59+
60+
On the other hand, if you'd like to start from scratch instead, you can run the following command to create
61+
a super user:
4962

5063
```bash
5164
./manage.py createsuperuser
5265
```
5366

67+
#### Start application
5468
Finally, you're ready to start the application:
5569

5670
```bash
@@ -69,3 +83,11 @@ codestyle.
6983
ln -s ../../tools/githook/pre-commit .git/hooks/
7084

7185
```
86+
87+
If you'd like to regenerate the database dump files, you can run the following commands:
88+
```
89+
./manage.py dumpdata auth --format=json --indent=4 --exclude=auth.permission > pgcommitfest/commitfest/fixtures/auth_data.json
90+
./manage.py dumpdata commitfest --format=json --indent=4 > pgcommitfest/commitfest/fixtures/commitfest_data.json
91+
```
92+
93+
If you want to reload data from dump file, you can run `drop owned by postgres;` in the `pgcommitfest` database first.

‎pgcommitfest/commitfest/ajax.py

+20
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import requests
1010
import json
1111
import textwrap
12+
import re
1213

1314
from pgcommitfest.auth import user_search
1415
from .models import CommitFest, Patch, MailThread, MailThreadAttachment
@@ -23,7 +24,26 @@ class Http503(Exception):
2324
pass
2425

2526

27+
def mockArchivesAPI(path):
28+
with open(settings.MOCK_ARCHIVE_DATA, 'r', encoding='utf-8') as file:
29+
data = json.load(file)
30+
for message in data:
31+
message['atts'] = []
32+
33+
message_pattern = re.compile(r"^/message-id\.json/(?P<message_id>[^/]+)$")
34+
35+
message_match = message_pattern.match(path)
36+
if message_match:
37+
message_id = message_match.group("message_id")
38+
return [message for message in data if message['msgid'] == message_id]
39+
else:
40+
return data
41+
42+
2643
def _archivesAPI(suburl, params=None):
44+
if getattr(settings, 'MOCK_ARCHIVES', False) and getattr(settings, 'MOCK_ARCHIVE_DATA'):
45+
return mockArchivesAPI(suburl)
46+
2747
try:
2848
resp = requests.get(
2949
"http{0}://{1}:{2}{3}".format(settings.ARCHIVES_PORT == 443 and 's' or '',

‎pgcommitfest/commitfest/fixtures/archive_data.json

+602
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[
2+
{
3+
"model": "auth.user",
4+
"pk": 1,
5+
"fields": {
6+
"password": "pbkdf2_sha256$600000$49rgHaLmmFQUm7c663LCrU$i68PFeI493lPmgNx/RHnWNuw4ZRzzvJWNqU4os5VnF4=",
7+
"last_login": "2025-01-26T10:43:07.735",
8+
"is_superuser": true,
9+
"username": "admin",
10+
"first_name": "",
11+
"last_name": "",
12+
"email": "test@test.com",
13+
"is_staff": true,
14+
"is_active": true,
15+
"date_joined": "2025-01-20T15:47:04.132",
16+
"groups": [],
17+
"user_permissions": []
18+
}
19+
}
20+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,373 @@
1+
[
2+
{
3+
"model": "commitfest.commitfest",
4+
"pk": 1,
5+
"fields": {
6+
"name": "Sample Old Commitfest",
7+
"status": 4,
8+
"startdate": "2024-05-01",
9+
"enddate": "2024-05-31"
10+
}
11+
},
12+
{
13+
"model": "commitfest.commitfest",
14+
"pk": 2,
15+
"fields": {
16+
"name": "Sample In Progress Commitfest",
17+
"status": 3,
18+
"startdate": "2025-01-01",
19+
"enddate": "2025-02-28"
20+
}
21+
},
22+
{
23+
"model": "commitfest.commitfest",
24+
"pk": 3,
25+
"fields": {
26+
"name": "Sample Open Commitfest",
27+
"status": 2,
28+
"startdate": "2025-03-01",
29+
"enddate": "2025-03-31"
30+
}
31+
},
32+
{
33+
"model": "commitfest.commitfest",
34+
"pk": 4,
35+
"fields": {
36+
"name": "Sample Future Commitfest",
37+
"status": 1,
38+
"startdate": "2025-05-01",
39+
"enddate": "2025-05-31"
40+
}
41+
},
42+
{
43+
"model": "commitfest.topic",
44+
"pk": 1,
45+
"fields": {
46+
"topic": "Bugs"
47+
}
48+
},
49+
{
50+
"model": "commitfest.topic",
51+
"pk": 2,
52+
"fields": {
53+
"topic": "Performance"
54+
}
55+
},
56+
{
57+
"model": "commitfest.topic",
58+
"pk": 3,
59+
"fields": {
60+
"topic": "Miscellaneous"
61+
}
62+
},
63+
{
64+
"model": "commitfest.targetversion",
65+
"pk": 1,
66+
"fields": {
67+
"version": "18"
68+
}
69+
},
70+
{
71+
"model": "commitfest.patch",
72+
"pk": 1,
73+
"fields": {
74+
"name": "Conflict detection for update_deleted in logical replication",
75+
"topic": 1,
76+
"wikilink": "",
77+
"gitlink": "",
78+
"targetversion": null,
79+
"committer": null,
80+
"created": "2025-01-26T10:48:31.579",
81+
"modified": "2025-01-26T10:53:20.498",
82+
"lastmail": "2025-01-20T06:53:39",
83+
"authors": [
84+
1
85+
],
86+
"reviewers": [],
87+
"subscribers": [],
88+
"mailthread_set": [
89+
1
90+
]
91+
}
92+
},
93+
{
94+
"model": "commitfest.patch",
95+
"pk": 2,
96+
"fields": {
97+
"name": "Sample rate added to pg_stat_statements",
98+
"topic": 3,
99+
"wikilink": "",
100+
"gitlink": "",
101+
"targetversion": null,
102+
"committer": null,
103+
"created": "2025-01-26T10:51:17.305",
104+
"modified": "2025-01-26T10:51:19.631",
105+
"lastmail": "2025-01-20T14:20:10",
106+
"authors": [],
107+
"reviewers": [],
108+
"subscribers": [],
109+
"mailthread_set": [
110+
2
111+
]
112+
}
113+
},
114+
{
115+
"model": "commitfest.patch",
116+
"pk": 3,
117+
"fields": {
118+
"name": "Per Backend I/O statistics",
119+
"topic": 3,
120+
"wikilink": "",
121+
"gitlink": "",
122+
"targetversion": null,
123+
"committer": null,
124+
"created": "2025-01-26T11:02:07.467",
125+
"modified": "2025-01-26T11:02:10.911",
126+
"lastmail": "2025-01-20T13:26:55",
127+
"authors": [],
128+
"reviewers": [],
129+
"subscribers": [],
130+
"mailthread_set": [
131+
3
132+
]
133+
}
134+
},
135+
{
136+
"model": "commitfest.patchoncommitfest",
137+
"pk": 1,
138+
"fields": {
139+
"patch": 1,
140+
"commitfest": 2,
141+
"enterdate": "2025-01-26T10:48:31.579",
142+
"leavedate": null,
143+
"status": 3
144+
}
145+
},
146+
{
147+
"model": "commitfest.patchoncommitfest",
148+
"pk": 2,
149+
"fields": {
150+
"patch": 2,
151+
"commitfest": 2,
152+
"enterdate": "2025-01-26T10:51:17.305",
153+
"leavedate": null,
154+
"status": 1
155+
}
156+
},
157+
{
158+
"model": "commitfest.patchoncommitfest",
159+
"pk": 3,
160+
"fields": {
161+
"patch": 1,
162+
"commitfest": 1,
163+
"enterdate": "2024-04-01T10:52:24",
164+
"leavedate": "2024-06-05T10:52:34",
165+
"status": 5
166+
}
167+
},
168+
{
169+
"model": "commitfest.patchoncommitfest",
170+
"pk": 4,
171+
"fields": {
172+
"patch": 3,
173+
"commitfest": 3,
174+
"enterdate": "2025-01-26T11:02:07.467",
175+
"leavedate": null,
176+
"status": 1
177+
}
178+
},
179+
{
180+
"model": "commitfest.patchhistory",
181+
"pk": 1,
182+
"fields": {
183+
"patch": 1,
184+
"date": "2025-01-26T10:48:31.580",
185+
"by": 1,
186+
"by_cfbot": false,
187+
"what": "Created patch record"
188+
}
189+
},
190+
{
191+
"model": "commitfest.patchhistory",
192+
"pk": 2,
193+
"fields": {
194+
"patch": 1,
195+
"date": "2025-01-26T10:48:31.582",
196+
"by": 1,
197+
"by_cfbot": false,
198+
"what": "Attached mail thread example@message-8"
199+
}
200+
},
201+
{
202+
"model": "commitfest.patchhistory",
203+
"pk": 3,
204+
"fields": {
205+
"patch": 1,
206+
"date": "2025-01-26T10:48:54.115",
207+
"by": 1,
208+
"by_cfbot": false,
209+
"what": "Changed authors to (admin)"
210+
}
211+
},
212+
{
213+
"model": "commitfest.patchhistory",
214+
"pk": 4,
215+
"fields": {
216+
"patch": 2,
217+
"date": "2025-01-26T10:51:17.306",
218+
"by": 1,
219+
"by_cfbot": false,
220+
"what": "Created patch record"
221+
}
222+
},
223+
{
224+
"model": "commitfest.patchhistory",
225+
"pk": 5,
226+
"fields": {
227+
"patch": 2,
228+
"date": "2025-01-26T10:51:17.307",
229+
"by": 1,
230+
"by_cfbot": false,
231+
"what": "Attached mail thread example@message-0"
232+
}
233+
},
234+
{
235+
"model": "commitfest.patchhistory",
236+
"pk": 6,
237+
"fields": {
238+
"patch": 1,
239+
"date": "2025-01-26T10:53:20.498",
240+
"by": 1,
241+
"by_cfbot": false,
242+
"what": "New status: Ready for Committer"
243+
}
244+
},
245+
{
246+
"model": "commitfest.patchhistory",
247+
"pk": 7,
248+
"fields": {
249+
"patch": 3,
250+
"date": "2025-01-26T11:02:07.468",
251+
"by": 1,
252+
"by_cfbot": false,
253+
"what": "Created patch record"
254+
}
255+
},
256+
{
257+
"model": "commitfest.patchhistory",
258+
"pk": 8,
259+
"fields": {
260+
"patch": 3,
261+
"date": "2025-01-26T11:02:07.469",
262+
"by": 1,
263+
"by_cfbot": false,
264+
"what": "Attached mail thread example@message-3"
265+
}
266+
},
267+
{
268+
"model": "commitfest.mailthread",
269+
"pk": 1,
270+
"fields": {
271+
"messageid": "example@message-8",
272+
"subject": "RE: Conflict detection for update_deleted in logical replication",
273+
"firstmessage": "2025-01-20T06:53:39",
274+
"firstauthor": "test@test.com",
275+
"latestmessage": "2025-01-20T06:53:39",
276+
"latestauthor": "test@test.com",
277+
"latestsubject": "RE: Conflict detection for update_deleted in logical replication",
278+
"latestmsgid": "example@message-8"
279+
}
280+
},
281+
{
282+
"model": "commitfest.mailthread",
283+
"pk": 2,
284+
"fields": {
285+
"messageid": "example@message-0",
286+
"subject": "Re: Sample rate added to pg_stat_statements",
287+
"firstmessage": "2025-01-20T14:20:10",
288+
"firstauthor": "test@test.com",
289+
"latestmessage": "2025-01-20T14:20:10",
290+
"latestauthor": "test@test.com",
291+
"latestsubject": "Re: Sample rate added to pg_stat_statements",
292+
"latestmsgid": "example@message-0"
293+
}
294+
},
295+
{
296+
"model": "commitfest.mailthread",
297+
"pk": 3,
298+
"fields": {
299+
"messageid": "example@message-3",
300+
"subject": "Re: per backend I/O statistics",
301+
"firstmessage": "2025-01-20T13:26:55",
302+
"firstauthor": "test@test.com",
303+
"latestmessage": "2025-01-20T13:26:55",
304+
"latestauthor": "test@test.com",
305+
"latestsubject": "Re: per backend I/O statistics",
306+
"latestmsgid": "example@message-3"
307+
}
308+
},
309+
{
310+
"model": "commitfest.patchstatus",
311+
"pk": 1,
312+
"fields": {
313+
"statusstring": "Needs review",
314+
"sortkey": 10
315+
}
316+
},
317+
{
318+
"model": "commitfest.patchstatus",
319+
"pk": 2,
320+
"fields": {
321+
"statusstring": "Waiting on Author",
322+
"sortkey": 15
323+
}
324+
},
325+
{
326+
"model": "commitfest.patchstatus",
327+
"pk": 3,
328+
"fields": {
329+
"statusstring": "Ready for Committer",
330+
"sortkey": 20
331+
}
332+
},
333+
{
334+
"model": "commitfest.patchstatus",
335+
"pk": 4,
336+
"fields": {
337+
"statusstring": "Committed",
338+
"sortkey": 25
339+
}
340+
},
341+
{
342+
"model": "commitfest.patchstatus",
343+
"pk": 5,
344+
"fields": {
345+
"statusstring": "Moved to next CF",
346+
"sortkey": 30
347+
}
348+
},
349+
{
350+
"model": "commitfest.patchstatus",
351+
"pk": 6,
352+
"fields": {
353+
"statusstring": "Rejected",
354+
"sortkey": 50
355+
}
356+
},
357+
{
358+
"model": "commitfest.patchstatus",
359+
"pk": 7,
360+
"fields": {
361+
"statusstring": "Returned with Feedback",
362+
"sortkey": 50
363+
}
364+
},
365+
{
366+
"model": "commitfest.patchstatus",
367+
"pk": 8,
368+
"fields": {
369+
"statusstring": "Withdrawn",
370+
"sortkey": 50
371+
}
372+
}
373+
]

‎pgcommitfest/commitfest/forms.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class PatchForm(forms.ModelForm):
4444

4545
class Meta:
4646
model = Patch
47-
exclude = ('commitfests', 'mailthreads', 'modified', 'lastmail', 'subscribers', )
47+
exclude = ('commitfests', 'mailthread_set', 'modified', 'lastmail', 'subscribers', )
4848

4949
def __init__(self, *args, **kwargs):
5050
super(PatchForm, self).__init__(*args, **kwargs)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Generated by Django 4.2.17 on 2025-01-25 11:14
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('commitfest', '0007_needs_rebase_emails'),
10+
]
11+
12+
operations = [
13+
migrations.RunSQL(
14+
migrations.RunSQL.noop,
15+
reverse_sql=migrations.RunSQL.noop,
16+
state_operations=[
17+
migrations.RemoveField(
18+
model_name='mailthread',
19+
name='patches',
20+
),
21+
migrations.AddField(
22+
model_name='patch',
23+
name='mailthread_set',
24+
field=models.ManyToManyField(db_table='commitfest_mailthread_patches', related_name='patches', to='commitfest.mailthread'),
25+
),
26+
]
27+
)
28+
]

‎pgcommitfest/commitfest/models.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ class Patch(models.Model, DiffableModel):
109109
# Users to be notified when something happens
110110
subscribers = models.ManyToManyField(User, related_name='patch_subscriber', blank=True)
111111

112+
mailthread_set = models.ManyToManyField("MailThread", related_name="patches", blank=False, db_table="commitfest_mailthread_patches")
113+
112114
# Datestamps for tracking activity
113115
created = models.DateTimeField(blank=False, null=False, auto_now_add=True)
114116
modified = models.DateTimeField(blank=False, null=False)
@@ -302,7 +304,6 @@ class MailThread(models.Model):
302304
# so we can keep track of when there was last a change on the
303305
# thread in question.
304306
messageid = models.CharField(max_length=1000, null=False, blank=False, unique=True)
305-
patches = models.ManyToManyField(Patch, blank=False)
306307
subject = models.CharField(max_length=500, null=False, blank=False)
307308
firstmessage = models.DateTimeField(null=False, blank=False)
308309
firstauthor = models.CharField(max_length=500, null=False, blank=False)

‎pgcommitfest/local_settings_example.py

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import os
2+
13
# Enable more debugging information
24
DEBUG = True
35
# Prevent logging to try to send emails to postgresql.org admins.
@@ -22,3 +24,7 @@
2224
# It's not great, because it won't redirect to the page you were trying to
2325
# access, but it's better than a HTTP 500 error.
2426
PGAUTH_REDIRECT = '/admin/login/'
27+
28+
MOCK_ARCHIVES = True
29+
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
30+
MOCK_ARCHIVE_DATA = os.path.join(BASE_DIR, 'commitfest', 'fixtures', 'archive_data.json')

0 commit comments

Comments
 (0)
Please sign in to comment.