comparison gpp/legacy/management/commands/import_old_users.py @ 290:64c188a9d31f

Adding a legacy app to contain management commands to convert the old data to the new database format. This first commit has the import_old_users command.
author Brian Neal <bgneal@gmail.com>
date Fri, 24 Dec 2010 05:28:58 +0000
parents
children a6357f2bcbbc
comparison
equal deleted inserted replaced
289:0dd8989abef2 290:64c188a9d31f
1 """
2 import_old_users.py - For importing users from SG101 1.0 as csv files.
3 """
4 from __future__ import with_statement
5 import csv
6 import optparse
7 import re
8 import sys
9 from datetime import datetime
10
11 import postmarkup
12
13 from django.core.management.base import LabelCommand, CommandError
14 from django.contrib.auth.models import User
15
16 import bio.models
17 from legacy.phpbb import unphpbb
18 from legacy.html2md import MarkdownWriter
19
20 TIME_ZONES = {
21 '-5': 'US/Eastern',
22 '-6': 'US/Central',
23 '-7': 'US/Mountain',
24 '-8': 'US/Pacific',
25 }
26 USERNAME_RE = re.compile(r'^[\w.@+-]+$')
27 USERNAME_LEN = (1, 30) # min & max length values
28
29
30 def _valid_username(username):
31 """
32 Return true if the username is valid.
33 """
34 return (USERNAME_LEN[0] <= len(username) <= USERNAME_LEN[1] and
35 USERNAME_RE.match(username))
36
37
38 def _break_name(name):
39 """
40 Break name into a first and last name.
41 Return a 2-tuple of first_name, last_name.
42 """
43 parts = name.split()
44 n = len(parts)
45 if n == 0:
46 t = '', ''
47 elif n == 1:
48 t = parts[0], ''
49 else:
50 t = ' '.join(parts[:-1]), parts[-1]
51 return t[0][:USERNAME_LEN[1]], t[1][:USERNAME_LEN[1]]
52
53
54 class Command(LabelCommand):
55 args = '<filename filename ...>'
56 help = 'Imports users from the old database in CSV format'
57 option_list = LabelCommand.option_list + (
58 optparse.make_option("-s", "--super-user",
59 help="Make the user with this name a superuser"),
60 optparse.make_option("-a", "--anon-user",
61 help="Make the user with this name the anonymous user "
62 "[default: Anonymous]"),
63 optparse.make_option("-p", "--progress", action="store_true",
64 help="Output a . after every 20 users to show progress"),
65 )
66 bb_parser = postmarkup.create(use_pygments=False, annotate_links=False)
67 md_writer = MarkdownWriter()
68
69 def handle_label(self, filename, **options):
70 """
71 Process each line in the CSV file given by filename by
72 creating a new user and profile.
73
74 """
75 self.superuser = options.get('super_user')
76 self.anonymous = options.get('anon_user')
77 if self.anonymous is None:
78 self.anonymous = 'Anonymous'
79 self.show_progress = options.get('progress')
80
81 if self.superuser == self.anonymous:
82 raise CommandError("super-user name should not match anon-user")
83
84 try:
85 with open(filename, "rb") as f:
86 self.reader = csv.DictReader(f)
87 num_rows = 0
88 try:
89 for row in self.reader:
90 self.process_row(row)
91 num_rows += 1
92 if num_rows % 20 == 0:
93 sys.stdout.write('.')
94 sys.stdout.flush()
95 except csv.Error, e:
96 raise CommandError("CSV error: %s %s %s" % (
97 filename, self.reader.line_num, e))
98
99 print
100
101 except IOError:
102 raise CommandError("Could not open file: %s" % filename)
103
104 def process_row(self, row):
105 """
106 Process one row from the CSV file: create a user and user profile for
107 the row and save it in the database.
108
109 """
110 row = dict((k, v if v != 'NULL' else '') for k, v in row.iteritems())
111
112 if not _valid_username(row['username']):
113 print "Skipping import of %s; invalid username" % row['username']
114 return
115
116 n = User.objects.filter(username=row['username']).count()
117 if n > 0:
118 print "Skipping import of %s; user already exists" % row['username']
119 return
120
121 first_name, last_name = _break_name(row['name'])
122 is_superuser = self.superuser == row['username']
123 is_anonymous = self.anonymous == row['username']
124
125 u = User(id=int(row['user_id']),
126 username=row['username'],
127 first_name=first_name,
128 last_name=last_name,
129 email=row['user_email'],
130 password=row['user_password'] if row['user_password'] else None,
131 is_staff=is_superuser,
132 is_active=True if not is_anonymous else False,
133 is_superuser=is_superuser,
134 last_login=datetime.fromtimestamp(int(row['user_lastvisit'])),
135 date_joined=datetime.strptime(row['user_regdate'], "%b %d, %Y"))
136
137 if is_anonymous:
138 u.set_unusable_password()
139
140 u.save()
141
142 p = u.get_profile()
143 p.location = row['user_from']
144 p.occupation = row['user_occ']
145 p.interests = row['user_interests']
146 p.profile_text = u''
147 p.hide_email = True if row['user_viewemail'] != '1' else False
148 p.signature = self.to_markdown(row['user_sig']) if row['user_sig'] else u''
149 p.time_zone = TIME_ZONES.get(row['user_timezone'], 'US/Pacific')
150 p.use_24_time = False
151 p.forum_post_count = int(row['user_posts'])
152 p.status = bio.models.STA_ACTIVE if p.forum_post_count > 10 else bio.models.STA_STRANGER
153 p.status_date = datetime.now()
154 p.update_date = p.status_date
155 p.save()
156
157 def to_html(self, s):
158 return self.bb_parser.render_to_html(unphpbb(s), cosmetic_replace=False)
159
160 def to_markdown(self, s):
161 self.md_writer.reset()
162 self.md_writer.feed(self.to_html(s))
163 return self.md_writer.markdown()