We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
New blurred database for development
Update the `db.sql` file.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `scripts/anonymizer.py`
Content:
```
1 import sys
2 from datetime import date, timedelta
3 import random
4 import shutil
5 import sqlite3
6 
7 #------------------------------------------------------------
8 
9 ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_'
10 
11 LOREM_IPSUM = [
12 '''Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a
13 diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam
14 viverra nec consectetur ante hendrerit. Donec et mollis
15 dolor. Praesent et diam eget libero egestas mattis sit amet vitae
16 augue. Nam tincidunt congue enim, ut porta lorem lacinia
17 consectetur. Donec ut libero sed arcu vehicula ultricies a non
18 tortor. Lorem ipsum dolor sit amet, consectetur adipiscing
19 elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed,
20 adipiscing id dolor. Pellentesque auctor nisi id magna consequat
21 sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt
22 feugiat nisl imperdiet. Ut convallis libero in urna ultrices
23 accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at
24 malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis
25 parturient montes, nascetur ridiculus mus. In rutrum accumsan
26 ultricies. Mauris vitae nisi at sem facilisis semper ac in est.'''
27 ,
28 '''Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut
29 tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper
30 ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi
31 diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec
32 pretium volutpat, arcu ante placerat erat, non tristique elit urna et
33 turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et
34 orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam,
35 elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis
36 pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod
37 ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo
38 sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at
39 massa ipsum. Quisque bibendum purus convallis nulla ultrices
40 ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit
41 laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat
42 elit. Nam sagittis nisi dui.'''
43 ,
44 '''Suspendisse lectus leo, consectetur in tempor sit amet, placerat quis
45 neque. Etiam luctus porttitor lorem, sed suscipit est rutrum
46 non. Curabitur lobortis nisl a enim congue semper. Aenean commodo
47 ultrices imperdiet. Vestibulum ut justo vel sapien venenatis
48 tincidunt. Phasellus eget dolor sit amet ipsum dapibus condimentum
49 vitae quis lectus. Aliquam ut massa in turpis dapibus
50 convallis. Praesent elit lacus, vestibulum at malesuada et, ornare et
51 est. Ut augue nunc, sodales ut euismod non, adipiscing vitae
52 orci. Mauris ut placerat justo. Mauris in ultricies enim. Quisque nec
53 est eleifend nulla ultrices egestas quis ut quam. Donec sollicitudin
54 lectus a mauris pulvinar id aliquam urna cursus. Cras quis ligula sem,
55 vel elementum mi. Phasellus non ullamcorper urna.'''
56 ,
57 '''Class aptent taciti sociosqu ad litora torquent per conubia nostra,
58 per inceptos himenaeos. In euismod ultrices facilisis. Vestibulum
59 porta sapien adipiscing augue congue id pretium lectus molestie. Proin
60 quis dictum nisl. Morbi id quam sapien, sed vestibulum sem. Duis
61 elementum rutrum mauris sed convallis. Proin vestibulum magna
62 mi. Aenean tristique hendrerit magna, ac facilisis nulla hendrerit
63 ut. Sed non tortor sodales quam auctor elementum. Donec hendrerit nunc
64 eget elit pharetra pulvinar. Suspendisse id tempus tortor. Aenean
65 luctus, elit commodo laoreet commodo, justo nisi consequat massa, sed
66 vulputate quam urna quis eros. Donec vel.''']
67 
68 #------------------------------------------------------------
69 
70 def get_one(cursor, statement, *params):
71     cursor.execute(statement, params)
72     results = cursor.fetchall()
73     if len(results) == 0:
74         return None
75     return results[0][0]
76 
77 RANDWORD_SEEN = set()
78 
79 def randword(low, high):
80     while True:
81         r = ''.join([random.choice(ALPHA) for i in range(random.randrange(low, high))])
82         if r not in RANDWORD_SEEN:
83             RANDWORD_SEEN.add(r)
84             return r
85 
86 def change(cursor, table, field, func, *args):
87     lower = get_one(cursor, 'select min(id) from {0};'.format(table))
88     upper = get_one(cursor, 'select max(id) from {0};'.format(table))
89     assert (lower is not None) and (upper is not None), \
90            'No lower/upper bounds for {0}.{1}'.format(table, field)
91 
92     if isinstance(field, str):
93         stmt = 'update {0} set {1}=? where id=?;'.format(table, field)
94     elif isinstance(field, tuple):
95         filler = ', '.join(['{0}=?'.format(f) for f in field])
96         stmt = 'update {0} set {1} where id=?;'.format(table, filler)
97     else:
98         assert False, 'Unknown field type "{0}" for "{1}"'.format(type(field), field)
99 
100     for i in range(lower, upper+1):
101         vals = func(cursor, i, *args) + (i, )
102         try:
103             cursor.execute(stmt, vals)
104         except sqlite3.OperationalError as e:
105             print('FAILED (operational error):', stmt, vals, e)
106         except sqlite3.IntegrityError as e:
107             print('FAILED (integrity error):', stmt, vals, e)
108 
109 def tuplify(func):
110     def f(*args, **kwargs):
111         result = func(*args, **kwargs)
112         return (result,)
113     return f
114 
115 #------------------------------------------------------------
116 
117 def dates(cursor, i):
118     '''Generate start and end dates for workshop.'''
119     start = date(2012, 1, 1) + timedelta(random.randrange(4 * 365))
120     end = start + timedelta(random.randrange(4))
121     if end == start:
122         end = None
123     return (start, end)
124 
125 @tuplify
126 def event_reg_key(cursor, i):
127     '''Generate random event registration key.'''
128     return str(1000000 + i)
129 
130 @tuplify
131 def event_slug(cursor, i):
132     '''Generate event slugs once start/end dates and site names are set.'''
133     start = get_one(cursor, 'select start from workshops_event where id=?;', i)
134     if start is None:
135         return
136     year, month, day = start.split('-')
137     return '{0}-{1}-{2}-{3}'.format(year, month, day, randword(3, 8))
138 
139 @tuplify
140 def url(cursor, i):
141     '''Generate something that looks like a URL.'''
142     _url = get_one(cursor, 'select url from workshops_event where id=?;', i)
143     if not _url:
144         return
145     return 'http://{0}.{1}/{2}-{3}'.format(*[randword(2, 10) for x in range(4)])
146 
147 @tuplify
148 def lorem_ipsum(cursor, i):
149     '''Fill in a large text field.'''
150     result = '\n'.join(LOREM_IPSUM[0:random.randrange(len(LOREM_IPSUM))])
151     return result
152 
153 @tuplify
154 def monicker(cursor, i):
155     '''Generate a username-style field.'''
156     return randword(2, 10)
157 
158 @tuplify
159 def multi_word(cursor, i, prob_multi, prob_null=0.0):
160     '''Fill in a multi-word field (e.g., site name or person's name).'''
161     if random.uniform(0.0, 1.0) < prob_null:
162         return None
163     elif random.uniform(0.0, 1.0) < prob_multi:
164         return '{0} {1}'.format(randword(2, 10), randword(2, 12))
165     else:
166         return randword(2, 10)
167 
168 @tuplify
169 def domain(cursor, i):
170     '''Fill in site.domain.'''
171     fields = []
172     for x in range(2, random.randrange(4, 5)):
173         fields.append(randword(2, 10))
174     return '.'.join(fields)
175 
176 @tuplify
177 def gender(cursor, i):
178     return random.choice('FMO')
179 
180 @tuplify
181 def email(cursor, i):
182     if random.uniform(0.0, 1.0) < 0.05:
183         return None
184     return '{0}@{1}.{2}'.format(*[randword(2, 8) for x in range(3)])
185 
186 
187 @tuplify
188 def empty_string(cursor, i):
189     return ''
190 
191 #------------------------------------------------------------
192 
193 def main():
194     assert len(sys.argv) == 4, 'Usage: {0} seed /path/to/source/db /path/to/destination/db'.format(sys.argv[0])
195     assert sys.argv[2] != sys.argv[3], 'Source and destination must be different database'
196 
197     seed = int(sys.argv[1])
198     if seed == 0:
199         seed = None
200     db_src = sys.argv[2]
201     db_dst = sys.argv[3]
202 
203     random.seed(seed)
204     shutil.copyfile(db_src, db_dst)
205     cnx = sqlite3.connect(db_dst)
206     cur = cnx.cursor()
207 
208     change(cur, 'workshops_site', 'domain', domain)
209     change(cur, 'workshops_site', 'fullname', multi_word, 1.0)
210     change(cur, 'workshops_site', 'notes', lorem_ipsum)
211 
212     change(cur, 'workshops_person', 'personal', multi_word, 0.1)
213     change(cur, 'workshops_person', 'middle', multi_word, 0.0, 0.9)
214     change(cur, 'workshops_person', 'family', multi_word, 0.1)
215     change(cur, 'workshops_person', 'gender', gender)
216     change(cur, 'workshops_person', 'email', email)
217     change(cur, 'workshops_person', 'github', monicker)
218     change(cur, 'workshops_person', 'twitter', monicker)
219     change(cur, 'workshops_person', 'url', url)
220     change(cur, 'workshops_person', 'username', monicker)
221     change(cur, 'workshops_person', 'password', empty_string)
222 
223     change(cur, 'workshops_event', ('start', 'end'), dates)
224     change(cur, 'workshops_event', 'slug', event_slug)
225     change(cur, 'workshops_event', 'url', url)
226     change(cur, 'workshops_event', 'reg_key', event_reg_key)
227     change(cur, 'workshops_event', 'notes', lorem_ipsum)
228 
229     # we can't store historical changes!
230     cur.execute('delete from reversion_version;')
231     cur.execute('delete from reversion_revision;')
232 
233     cnx.commit()
234     cur.close()
235     cnx.close()
236 
237 if __name__ == '__main__':
238     main()
239     # we need to populate reversion_* tables so that no-one needs to do that
240     # upon every `make database` call
241     print("REMEMBER! to run `./manage.py createinitialrevisions` on the new database NOW")
242
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/scripts/anonymizer.py b/scripts/anonymizer.py
--- a/scripts/anonymizer.py
+++ b/scripts/anonymizer.py
@@ -147,6 +147,8 @@
 @tuplify
 def lorem_ipsum(cursor, i):
     '''Fill in a large text field.'''
+    if random.uniform(0.0, 1.0) < 0.05:
+        return ''
     result = '\n'.join(LOREM_IPSUM[0:random.randrange(len(LOREM_IPSUM))])
     return result
 
@@ -188,6 +190,17 @@
 def empty_string(cursor, i):
     return ''
 
+
+@tuplify
+def rand_latitude(cursor, i):
+    return random.uniform(-90, 90)
+
+
+@tuplify
+def rand_longitude(cursor, i):
+    return random.uniform(0, 180)
+
+
 #------------------------------------------------------------
 
 def main():
@@ -205,9 +218,9 @@
     cnx = sqlite3.connect(db_dst)
     cur = cnx.cursor()
 
-    change(cur, 'workshops_site', 'domain', domain)
-    change(cur, 'workshops_site', 'fullname', multi_word, 1.0)
-    change(cur, 'workshops_site', 'notes', lorem_ipsum)
+    change(cur, 'workshops_host', 'domain', domain)
+    change(cur, 'workshops_host', 'fullname', multi_word, 1.0)
+    change(cur, 'workshops_host', 'notes', lorem_ipsum)
 
     change(cur, 'workshops_person', 'personal', multi_word, 0.1)
     change(cur, 'workshops_person', 'middle', multi_word, 0.0, 0.9)
@@ -219,10 +232,16 @@
     change(cur, 'workshops_person', 'url', url)
     change(cur, 'workshops_person', 'username', monicker)
     change(cur, 'workshops_person', 'password', empty_string)
+    change(cur, 'workshops_person', 'affiliation', empty_string)
 
     change(cur, 'workshops_event', ('start', 'end'), dates)
     change(cur, 'workshops_event', 'slug', event_slug)
     change(cur, 'workshops_event', 'url', url)
+    change(cur, 'workshops_event', 'contact', empty_string)
+    change(cur, 'workshops_event', 'venue', empty_string)
+    change(cur, 'workshops_event', 'address', empty_string)
+    change(cur, 'workshops_event', 'latitude', rand_latitude)
+    change(cur, 'workshops_event', 'longitude', rand_longitude)
     change(cur, 'workshops_event', 'reg_key', event_reg_key)
     change(cur, 'workshops_event', 'notes', lorem_ipsum)
 
@@ -238,4 +257,6 @@
     main()
     # we need to populate reversion_* tables so that no-one needs to do that
     # upon every `make database` call
-    print("REMEMBER! to run `./manage.py createinitialrevisions` on the new database NOW")
+    print("REMEMBER! to run `./manage.py createinitialrevisions` on the new "
+          "database NOW.")
+    print("Next, run `sqlite3 SRC -cmd '.dump' > DEST.sql`")

{"golden_diff": "diff --git a/scripts/anonymizer.py b/scripts/anonymizer.py\n--- a/scripts/anonymizer.py\n+++ b/scripts/anonymizer.py\n@@ -147,6 +147,8 @@\n @tuplify\n def lorem_ipsum(cursor, i):\n     '''Fill in a large text field.'''\n+    if random.uniform(0.0, 1.0) < 0.05:\n+        return ''\n     result = '\\n'.join(LOREM_IPSUM[0:random.randrange(len(LOREM_IPSUM))])\n     return result\n \n@@ -188,6 +190,17 @@\n def empty_string(cursor, i):\n     return ''\n \n+\n+@tuplify\n+def rand_latitude(cursor, i):\n+    return random.uniform(-90, 90)\n+\n+\n+@tuplify\n+def rand_longitude(cursor, i):\n+    return random.uniform(0, 180)\n+\n+\n #------------------------------------------------------------\n \n def main():\n@@ -205,9 +218,9 @@\n     cnx = sqlite3.connect(db_dst)\n     cur = cnx.cursor()\n \n-    change(cur, 'workshops_site', 'domain', domain)\n-    change(cur, 'workshops_site', 'fullname', multi_word, 1.0)\n-    change(cur, 'workshops_site', 'notes', lorem_ipsum)\n+    change(cur, 'workshops_host', 'domain', domain)\n+    change(cur, 'workshops_host', 'fullname', multi_word, 1.0)\n+    change(cur, 'workshops_host', 'notes', lorem_ipsum)\n \n     change(cur, 'workshops_person', 'personal', multi_word, 0.1)\n     change(cur, 'workshops_person', 'middle', multi_word, 0.0, 0.9)\n@@ -219,10 +232,16 @@\n     change(cur, 'workshops_person', 'url', url)\n     change(cur, 'workshops_person', 'username', monicker)\n     change(cur, 'workshops_person', 'password', empty_string)\n+    change(cur, 'workshops_person', 'affiliation', empty_string)\n \n     change(cur, 'workshops_event', ('start', 'end'), dates)\n     change(cur, 'workshops_event', 'slug', event_slug)\n     change(cur, 'workshops_event', 'url', url)\n+    change(cur, 'workshops_event', 'contact', empty_string)\n+    change(cur, 'workshops_event', 'venue', empty_string)\n+    change(cur, 'workshops_event', 'address', empty_string)\n+    change(cur, 'workshops_event', 'latitude', rand_latitude)\n+    change(cur, 'workshops_event', 'longitude', rand_longitude)\n     change(cur, 'workshops_event', 'reg_key', event_reg_key)\n     change(cur, 'workshops_event', 'notes', lorem_ipsum)\n \n@@ -238,4 +257,6 @@\n     main()\n     # we need to populate reversion_* tables so that no-one needs to do that\n     # upon every `make database` call\n-    print(\"REMEMBER! to run `./manage.py createinitialrevisions` on the new database NOW\")\n+    print(\"REMEMBER! to run `./manage.py createinitialrevisions` on the new \"\n+          \"database NOW.\")\n+    print(\"Next, run `sqlite3 SRC -cmd '.dump' > DEST.sql`\")\n", "issue": "New blurred database for development\nUpdate the `db.sql` file.\n\n", "before_files": [{"content": "import sys\nfrom datetime import date, timedelta\nimport random\nimport shutil\nimport sqlite3\n\n#------------------------------------------------------------\n\nALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_'\n\nLOREM_IPSUM = [\n'''Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a\ndiam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam\nviverra nec consectetur ante hendrerit. Donec et mollis\ndolor. Praesent et diam eget libero egestas mattis sit amet vitae\naugue. Nam tincidunt congue enim, ut porta lorem lacinia\nconsectetur. Donec ut libero sed arcu vehicula ultricies a non\ntortor. Lorem ipsum dolor sit amet, consectetur adipiscing\nelit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed,\nadipiscing id dolor. Pellentesque auctor nisi id magna consequat\nsagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt\nfeugiat nisl imperdiet. Ut convallis libero in urna ultrices\naccumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at\nmalesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis\nparturient montes, nascetur ridiculus mus. In rutrum accumsan\nultricies. Mauris vitae nisi at sem facilisis semper ac in est.'''\n,\n'''Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut\ntristique vitae, sagittis vel odio. Maecenas convallis ullamcorper\nultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi\ndiam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec\npretium volutpat, arcu ante placerat erat, non tristique elit urna et\nturpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et\norci. Fusce eget orci a orci congue vestibulum. Ut dolor diam,\nelementum et vestibulum eu, porttitor vel elit. Curabitur venenatis\npulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod\nultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo\nsodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at\nmassa ipsum. Quisque bibendum purus convallis nulla ultrices\nultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit\nlaoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat\nelit. Nam sagittis nisi dui.'''\n,\n'''Suspendisse lectus leo, consectetur in tempor sit amet, placerat quis\nneque. Etiam luctus porttitor lorem, sed suscipit est rutrum\nnon. Curabitur lobortis nisl a enim congue semper. Aenean commodo\nultrices imperdiet. Vestibulum ut justo vel sapien venenatis\ntincidunt. Phasellus eget dolor sit amet ipsum dapibus condimentum\nvitae quis lectus. Aliquam ut massa in turpis dapibus\nconvallis. Praesent elit lacus, vestibulum at malesuada et, ornare et\nest. Ut augue nunc, sodales ut euismod non, adipiscing vitae\norci. Mauris ut placerat justo. Mauris in ultricies enim. Quisque nec\nest eleifend nulla ultrices egestas quis ut quam. Donec sollicitudin\nlectus a mauris pulvinar id aliquam urna cursus. Cras quis ligula sem,\nvel elementum mi. Phasellus non ullamcorper urna.'''\n,\n'''Class aptent taciti sociosqu ad litora torquent per conubia nostra,\nper inceptos himenaeos. In euismod ultrices facilisis. Vestibulum\nporta sapien adipiscing augue congue id pretium lectus molestie. Proin\nquis dictum nisl. Morbi id quam sapien, sed vestibulum sem. Duis\nelementum rutrum mauris sed convallis. Proin vestibulum magna\nmi. Aenean tristique hendrerit magna, ac facilisis nulla hendrerit\nut. Sed non tortor sodales quam auctor elementum. Donec hendrerit nunc\neget elit pharetra pulvinar. Suspendisse id tempus tortor. Aenean\nluctus, elit commodo laoreet commodo, justo nisi consequat massa, sed\nvulputate quam urna quis eros. Donec vel.''']\n\n#------------------------------------------------------------\n\ndef get_one(cursor, statement, *params):\n    cursor.execute(statement, params)\n    results = cursor.fetchall()\n    if len(results) == 0:\n        return None\n    return results[0][0]\n\nRANDWORD_SEEN = set()\n\ndef randword(low, high):\n    while True:\n        r = ''.join([random.choice(ALPHA) for i in range(random.randrange(low, high))])\n        if r not in RANDWORD_SEEN:\n            RANDWORD_SEEN.add(r)\n            return r\n\ndef change(cursor, table, field, func, *args):\n    lower = get_one(cursor, 'select min(id) from {0};'.format(table))\n    upper = get_one(cursor, 'select max(id) from {0};'.format(table))\n    assert (lower is not None) and (upper is not None), \\\n           'No lower/upper bounds for {0}.{1}'.format(table, field)\n\n    if isinstance(field, str):\n        stmt = 'update {0} set {1}=? where id=?;'.format(table, field)\n    elif isinstance(field, tuple):\n        filler = ', '.join(['{0}=?'.format(f) for f in field])\n        stmt = 'update {0} set {1} where id=?;'.format(table, filler)\n    else:\n        assert False, 'Unknown field type \"{0}\" for \"{1}\"'.format(type(field), field)\n\n    for i in range(lower, upper+1):\n        vals = func(cursor, i, *args) + (i, )\n        try:\n            cursor.execute(stmt, vals)\n        except sqlite3.OperationalError as e:\n            print('FAILED (operational error):', stmt, vals, e)\n        except sqlite3.IntegrityError as e:\n            print('FAILED (integrity error):', stmt, vals, e)\n\ndef tuplify(func):\n    def f(*args, **kwargs):\n        result = func(*args, **kwargs)\n        return (result,)\n    return f\n\n#------------------------------------------------------------\n\ndef dates(cursor, i):\n    '''Generate start and end dates for workshop.'''\n    start = date(2012, 1, 1) + timedelta(random.randrange(4 * 365))\n    end = start + timedelta(random.randrange(4))\n    if end == start:\n        end = None\n    return (start, end)\n\n@tuplify\ndef event_reg_key(cursor, i):\n    '''Generate random event registration key.'''\n    return str(1000000 + i)\n\n@tuplify\ndef event_slug(cursor, i):\n    '''Generate event slugs once start/end dates and site names are set.'''\n    start = get_one(cursor, 'select start from workshops_event where id=?;', i)\n    if start is None:\n        return\n    year, month, day = start.split('-')\n    return '{0}-{1}-{2}-{3}'.format(year, month, day, randword(3, 8))\n\n@tuplify\ndef url(cursor, i):\n    '''Generate something that looks like a URL.'''\n    _url = get_one(cursor, 'select url from workshops_event where id=?;', i)\n    if not _url:\n        return\n    return 'http://{0}.{1}/{2}-{3}'.format(*[randword(2, 10) for x in range(4)])\n\n@tuplify\ndef lorem_ipsum(cursor, i):\n    '''Fill in a large text field.'''\n    result = '\\n'.join(LOREM_IPSUM[0:random.randrange(len(LOREM_IPSUM))])\n    return result\n\n@tuplify\ndef monicker(cursor, i):\n    '''Generate a username-style field.'''\n    return randword(2, 10)\n\n@tuplify\ndef multi_word(cursor, i, prob_multi, prob_null=0.0):\n    '''Fill in a multi-word field (e.g., site name or person's name).'''\n    if random.uniform(0.0, 1.0) < prob_null:\n        return None\n    elif random.uniform(0.0, 1.0) < prob_multi:\n        return '{0} {1}'.format(randword(2, 10), randword(2, 12))\n    else:\n        return randword(2, 10)\n\n@tuplify\ndef domain(cursor, i):\n    '''Fill in site.domain.'''\n    fields = []\n    for x in range(2, random.randrange(4, 5)):\n        fields.append(randword(2, 10))\n    return '.'.join(fields)\n\n@tuplify\ndef gender(cursor, i):\n    return random.choice('FMO')\n\n@tuplify\ndef email(cursor, i):\n    if random.uniform(0.0, 1.0) < 0.05:\n        return None\n    return '{0}@{1}.{2}'.format(*[randword(2, 8) for x in range(3)])\n\n\n@tuplify\ndef empty_string(cursor, i):\n    return ''\n\n#------------------------------------------------------------\n\ndef main():\n    assert len(sys.argv) == 4, 'Usage: {0} seed /path/to/source/db /path/to/destination/db'.format(sys.argv[0])\n    assert sys.argv[2] != sys.argv[3], 'Source and destination must be different database'\n\n    seed = int(sys.argv[1])\n    if seed == 0:\n        seed = None\n    db_src = sys.argv[2]\n    db_dst = sys.argv[3]\n\n    random.seed(seed)\n    shutil.copyfile(db_src, db_dst)\n    cnx = sqlite3.connect(db_dst)\n    cur = cnx.cursor()\n\n    change(cur, 'workshops_site', 'domain', domain)\n    change(cur, 'workshops_site', 'fullname', multi_word, 1.0)\n    change(cur, 'workshops_site', 'notes', lorem_ipsum)\n\n    change(cur, 'workshops_person', 'personal', multi_word, 0.1)\n    change(cur, 'workshops_person', 'middle', multi_word, 0.0, 0.9)\n    change(cur, 'workshops_person', 'family', multi_word, 0.1)\n    change(cur, 'workshops_person', 'gender', gender)\n    change(cur, 'workshops_person', 'email', email)\n    change(cur, 'workshops_person', 'github', monicker)\n    change(cur, 'workshops_person', 'twitter', monicker)\n    change(cur, 'workshops_person', 'url', url)\n    change(cur, 'workshops_person', 'username', monicker)\n    change(cur, 'workshops_person', 'password', empty_string)\n\n    change(cur, 'workshops_event', ('start', 'end'), dates)\n    change(cur, 'workshops_event', 'slug', event_slug)\n    change(cur, 'workshops_event', 'url', url)\n    change(cur, 'workshops_event', 'reg_key', event_reg_key)\n    change(cur, 'workshops_event', 'notes', lorem_ipsum)\n\n    # we can't store historical changes!\n    cur.execute('delete from reversion_version;')\n    cur.execute('delete from reversion_revision;')\n\n    cnx.commit()\n    cur.close()\n    cnx.close()\n\nif __name__ == '__main__':\n    main()\n    # we need to populate reversion_* tables so that no-one needs to do that\n    # upon every `make database` call\n    print(\"REMEMBER! to run `./manage.py createinitialrevisions` on the new database NOW\")\n", "path": "scripts/anonymizer.py"}], "after_files": [{"content": "import sys\nfrom datetime import date, timedelta\nimport random\nimport shutil\nimport sqlite3\n\n#------------------------------------------------------------\n\nALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_'\n\nLOREM_IPSUM = [\n'''Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a\ndiam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam\nviverra nec consectetur ante hendrerit. Donec et mollis\ndolor. Praesent et diam eget libero egestas mattis sit amet vitae\naugue. Nam tincidunt congue enim, ut porta lorem lacinia\nconsectetur. Donec ut libero sed arcu vehicula ultricies a non\ntortor. Lorem ipsum dolor sit amet, consectetur adipiscing\nelit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed,\nadipiscing id dolor. Pellentesque auctor nisi id magna consequat\nsagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt\nfeugiat nisl imperdiet. Ut convallis libero in urna ultrices\naccumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at\nmalesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis\nparturient montes, nascetur ridiculus mus. In rutrum accumsan\nultricies. Mauris vitae nisi at sem facilisis semper ac in est.'''\n,\n'''Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut\ntristique vitae, sagittis vel odio. Maecenas convallis ullamcorper\nultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi\ndiam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec\npretium volutpat, arcu ante placerat erat, non tristique elit urna et\nturpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et\norci. Fusce eget orci a orci congue vestibulum. Ut dolor diam,\nelementum et vestibulum eu, porttitor vel elit. Curabitur venenatis\npulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod\nultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo\nsodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at\nmassa ipsum. Quisque bibendum purus convallis nulla ultrices\nultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit\nlaoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat\nelit. Nam sagittis nisi dui.'''\n,\n'''Suspendisse lectus leo, consectetur in tempor sit amet, placerat quis\nneque. Etiam luctus porttitor lorem, sed suscipit est rutrum\nnon. Curabitur lobortis nisl a enim congue semper. Aenean commodo\nultrices imperdiet. Vestibulum ut justo vel sapien venenatis\ntincidunt. Phasellus eget dolor sit amet ipsum dapibus condimentum\nvitae quis lectus. Aliquam ut massa in turpis dapibus\nconvallis. Praesent elit lacus, vestibulum at malesuada et, ornare et\nest. Ut augue nunc, sodales ut euismod non, adipiscing vitae\norci. Mauris ut placerat justo. Mauris in ultricies enim. Quisque nec\nest eleifend nulla ultrices egestas quis ut quam. Donec sollicitudin\nlectus a mauris pulvinar id aliquam urna cursus. Cras quis ligula sem,\nvel elementum mi. Phasellus non ullamcorper urna.'''\n,\n'''Class aptent taciti sociosqu ad litora torquent per conubia nostra,\nper inceptos himenaeos. In euismod ultrices facilisis. Vestibulum\nporta sapien adipiscing augue congue id pretium lectus molestie. Proin\nquis dictum nisl. Morbi id quam sapien, sed vestibulum sem. Duis\nelementum rutrum mauris sed convallis. Proin vestibulum magna\nmi. Aenean tristique hendrerit magna, ac facilisis nulla hendrerit\nut. Sed non tortor sodales quam auctor elementum. Donec hendrerit nunc\neget elit pharetra pulvinar. Suspendisse id tempus tortor. Aenean\nluctus, elit commodo laoreet commodo, justo nisi consequat massa, sed\nvulputate quam urna quis eros. Donec vel.''']\n\n#------------------------------------------------------------\n\ndef get_one(cursor, statement, *params):\n    cursor.execute(statement, params)\n    results = cursor.fetchall()\n    if len(results) == 0:\n        return None\n    return results[0][0]\n\nRANDWORD_SEEN = set()\n\ndef randword(low, high):\n    while True:\n        r = ''.join([random.choice(ALPHA) for i in range(random.randrange(low, high))])\n        if r not in RANDWORD_SEEN:\n            RANDWORD_SEEN.add(r)\n            return r\n\ndef change(cursor, table, field, func, *args):\n    lower = get_one(cursor, 'select min(id) from {0};'.format(table))\n    upper = get_one(cursor, 'select max(id) from {0};'.format(table))\n    assert (lower is not None) and (upper is not None), \\\n           'No lower/upper bounds for {0}.{1}'.format(table, field)\n\n    if isinstance(field, str):\n        stmt = 'update {0} set {1}=? where id=?;'.format(table, field)\n    elif isinstance(field, tuple):\n        filler = ', '.join(['{0}=?'.format(f) for f in field])\n        stmt = 'update {0} set {1} where id=?;'.format(table, filler)\n    else:\n        assert False, 'Unknown field type \"{0}\" for \"{1}\"'.format(type(field), field)\n\n    for i in range(lower, upper+1):\n        vals = func(cursor, i, *args) + (i, )\n        try:\n            cursor.execute(stmt, vals)\n        except sqlite3.OperationalError as e:\n            print('FAILED (operational error):', stmt, vals, e)\n        except sqlite3.IntegrityError as e:\n            print('FAILED (integrity error):', stmt, vals, e)\n\ndef tuplify(func):\n    def f(*args, **kwargs):\n        result = func(*args, **kwargs)\n        return (result,)\n    return f\n\n#------------------------------------------------------------\n\ndef dates(cursor, i):\n    '''Generate start and end dates for workshop.'''\n    start = date(2012, 1, 1) + timedelta(random.randrange(4 * 365))\n    end = start + timedelta(random.randrange(4))\n    if end == start:\n        end = None\n    return (start, end)\n\n@tuplify\ndef event_reg_key(cursor, i):\n    '''Generate random event registration key.'''\n    return str(1000000 + i)\n\n@tuplify\ndef event_slug(cursor, i):\n    '''Generate event slugs once start/end dates and site names are set.'''\n    start = get_one(cursor, 'select start from workshops_event where id=?;', i)\n    if start is None:\n        return\n    year, month, day = start.split('-')\n    return '{0}-{1}-{2}-{3}'.format(year, month, day, randword(3, 8))\n\n@tuplify\ndef url(cursor, i):\n    '''Generate something that looks like a URL.'''\n    _url = get_one(cursor, 'select url from workshops_event where id=?;', i)\n    if not _url:\n        return\n    return 'http://{0}.{1}/{2}-{3}'.format(*[randword(2, 10) for x in range(4)])\n\n@tuplify\ndef lorem_ipsum(cursor, i):\n    '''Fill in a large text field.'''\n    if random.uniform(0.0, 1.0) < 0.05:\n        return ''\n    result = '\\n'.join(LOREM_IPSUM[0:random.randrange(len(LOREM_IPSUM))])\n    return result\n\n@tuplify\ndef monicker(cursor, i):\n    '''Generate a username-style field.'''\n    return randword(2, 10)\n\n@tuplify\ndef multi_word(cursor, i, prob_multi, prob_null=0.0):\n    '''Fill in a multi-word field (e.g., site name or person's name).'''\n    if random.uniform(0.0, 1.0) < prob_null:\n        return None\n    elif random.uniform(0.0, 1.0) < prob_multi:\n        return '{0} {1}'.format(randword(2, 10), randword(2, 12))\n    else:\n        return randword(2, 10)\n\n@tuplify\ndef domain(cursor, i):\n    '''Fill in site.domain.'''\n    fields = []\n    for x in range(2, random.randrange(4, 5)):\n        fields.append(randword(2, 10))\n    return '.'.join(fields)\n\n@tuplify\ndef gender(cursor, i):\n    return random.choice('FMO')\n\n@tuplify\ndef email(cursor, i):\n    if random.uniform(0.0, 1.0) < 0.05:\n        return None\n    return '{0}@{1}.{2}'.format(*[randword(2, 8) for x in range(3)])\n\n\n@tuplify\ndef empty_string(cursor, i):\n    return ''\n\n\n@tuplify\ndef rand_latitude(cursor, i):\n    return random.uniform(-90, 90)\n\n\n@tuplify\ndef rand_longitude(cursor, i):\n    return random.uniform(0, 180)\n\n\n#------------------------------------------------------------\n\ndef main():\n    assert len(sys.argv) == 4, 'Usage: {0} seed /path/to/source/db /path/to/destination/db'.format(sys.argv[0])\n    assert sys.argv[2] != sys.argv[3], 'Source and destination must be different database'\n\n    seed = int(sys.argv[1])\n    if seed == 0:\n        seed = None\n    db_src = sys.argv[2]\n    db_dst = sys.argv[3]\n\n    random.seed(seed)\n    shutil.copyfile(db_src, db_dst)\n    cnx = sqlite3.connect(db_dst)\n    cur = cnx.cursor()\n\n    change(cur, 'workshops_host', 'domain', domain)\n    change(cur, 'workshops_host', 'fullname', multi_word, 1.0)\n    change(cur, 'workshops_host', 'notes', lorem_ipsum)\n\n    change(cur, 'workshops_person', 'personal', multi_word, 0.1)\n    change(cur, 'workshops_person', 'middle', multi_word, 0.0, 0.9)\n    change(cur, 'workshops_person', 'family', multi_word, 0.1)\n    change(cur, 'workshops_person', 'gender', gender)\n    change(cur, 'workshops_person', 'email', email)\n    change(cur, 'workshops_person', 'github', monicker)\n    change(cur, 'workshops_person', 'twitter', monicker)\n    change(cur, 'workshops_person', 'url', url)\n    change(cur, 'workshops_person', 'username', monicker)\n    change(cur, 'workshops_person', 'password', empty_string)\n    change(cur, 'workshops_person', 'affiliation', empty_string)\n\n    change(cur, 'workshops_event', ('start', 'end'), dates)\n    change(cur, 'workshops_event', 'slug', event_slug)\n    change(cur, 'workshops_event', 'url', url)\n    change(cur, 'workshops_event', 'contact', empty_string)\n    change(cur, 'workshops_event', 'venue', empty_string)\n    change(cur, 'workshops_event', 'address', empty_string)\n    change(cur, 'workshops_event', 'latitude', rand_latitude)\n    change(cur, 'workshops_event', 'longitude', rand_longitude)\n    change(cur, 'workshops_event', 'reg_key', event_reg_key)\n    change(cur, 'workshops_event', 'notes', lorem_ipsum)\n\n    # we can't store historical changes!\n    cur.execute('delete from reversion_version;')\n    cur.execute('delete from reversion_revision;')\n\n    cnx.commit()\n    cur.close()\n    cnx.close()\n\nif __name__ == '__main__':\n    main()\n    # we need to populate reversion_* tables so that no-one needs to do that\n    # upon every `make database` call\n    print(\"REMEMBER! to run `./manage.py createinitialrevisions` on the new \"\n          \"database NOW.\")\n    print(\"Next, run `sqlite3 SRC -cmd '.dump' > DEST.sql`\")\n", "path": "scripts/anonymizer.py"}]}