Edgewall Software

Ticket #5241: mw2tw.py

File mw2tw.py, 6.3 KB (added by jason.dusek@…, 4 years ago)

Grabs image data and puts it into the Trac tables. Links are more nicely formatted.

Line 
1#!/usr/bin/python
2"""
3  This script is provided AS IS, without any warranty!
4  Copyright lio@lunesu.com, placed in the public domain
5  Modified by Koen Werdler @ 01-05-2007
6  Modified by Jason Dusek, 2008-07-15Z
7 
8  Requirements:
9 .  python 2.5
10 .  python-mysqldb
11
12  This script dumps every version of every page as an INSERT statement that
13  is compatible with the SQLite Trac schema (don't know about other
14  databases). It omits some functionality, like recognizing edits by IP
15  address users.
16
17  You can set the connection parameters towards the bottom of the script
18  (following "main program").
19                                                                           """
20
21import re
22import os
23import sys
24import time
25import string
26import _mysql
27
28
29
30
31def q(s):
32    return "'" + s.replace("'", "''") + "'"
33
34def time_fixer(mw_time):
35    """ convert from mediawiki dates to epoch seconds """
36    t = time.mktime(time.strptime(mw_time, "%Y%m%d%H%M%S"))
37    return int(t)
38
39pairs = [
40    ("\n***","\n   *"),
41    ("\n**", "\n  *"),
42    ("\n*",  "\n *"),
43    ("<br>","[[BR]]"),
44    ("\n:","\n "),
45    ]
46
47wiki_link_catcher = re.compile(r"""
48    \[\[
49      \s*
50        ([^|\[\]]+?)        ##  non-greedy `+?` to chop trailing space
51      \s*
52        (\|
53          \s*
54            ([^\[\]]+?)     ##  non-greedy `+?` to chop trailing space
55          \s*
56        )?
57    \]\]
58    """, 
59    re.VERBOSE,
60    )
61
62def link_rewriter(match):
63    (link, label) = match.group(1, 3)
64    def wrap(a, b=()):
65        return '[wiki:' + a.replace(' ', '_') + ' ' + (b or a) + ' ]'
66    if link.startswith("Image:"):
67        return '[[Image(wiki:Image/' + link[6:] + ':' + link[6:] + ')]]'
68    return wrap(link, label) 
69
70def text_fixer(mw_text):
71    """ convert from mediawiki text to trac text """
72    for (mw, tw) in pairs:
73        mw_text = mw_text.replace(mw, tw)
74    return q(wiki_link_catcher.sub(link_rewriter, mw_text))
75
76def title_fixer(namespace, title):
77    if namespace is 0:
78        return q(title)
79    if namespace is 1:
80        return q('Talk:' + title)
81    if namespace is 2:
82        return q('User:' + title)
83    if namespace is 6:
84        return q('Image/' + title)
85
86def comment_fixer(mw_comment):
87    if mw_comment == '':
88        return 'NULL'
89    else:
90        return q(mw_comment)
91
92def row_writer(row):
93    inserts = [(
94        'wiki',
95        [   title_fixer(int(row[-2]), row[0]),
96            str(row[1]),
97            str(time_fixer(row[2])),
98            q(row[3]),
99            "'127.0.0.1'",
100            text_fixer(row[4]),
101            comment_fixer(row[5]),
102            'NULL'
103        ])]
104    if inserts[0][1][0].startswith("'Image/"):  ##  mind the quote
105        inserts += [(
106            'attachment',
107            [   q('wiki'), 
108                inserts[0][1][0],
109                "'" + inserts[0][1][0][7:],     ##  mind the quote
110                str(row[-3]),
111                inserts[0][1][2],
112                inserts[0][1][6],
113                inserts[0][1][3],
114                "'127.0.0.1'",
115            ])]
116    def ins(stuff):
117        (t, e) = stuff
118        return "INSERT INTO " + t + " VALUES\n(\t" + ",\n\t".join(e) + "\n);"
119    return "\n".join([ ins(insert) for insert in inserts ]) 
120
121"""
122  The tables in the Trac schema that we are trying to fake:
123
124CREATE TABLE wiki (
125    name text,
126    version integer,
127    time integer,
128    author text,
129    ipnr text,
130    text text,
131    comment text,
132    readonly integer,
133    UNIQUE (name,version)
134);
135
136CREATE TABLE attachment (
137    type text,
138    id text,
139    filename text,
140    size integer,
141    time integer,
142    description text,
143    author text,
144    ipnr text,
145    UNIQUE (type,id,filename)
146);
147                                                                           """
148
149
150
151
152"""
153  Failings of this query:
154 .  Does not handle "IP address" (anonymous) users.
155 .  Does not handle User_talk pages.
156                                                                           """
157query = string.Template("""
158    SELECT
159        ${p}page.page_title,
160        ${p}revision.rev_timestamp,
161        ${p}user.user_name,
162        ${p}text.old_text,
163        ${p}revision.rev_comment,
164        /* the 'meta' elements follow */
165        ${p}image.img_size,
166        ${p}page.page_namespace,
167        ${p}revision.rev_page
168      FROM
169        ${p}page,
170        ${p}revision,
171        ${p}user,
172        ${p}text
173      LEFT JOIN ${p}image ON
174        ${p}page.page_title = ${p}image.img_name
175      WHERE
176        ${p}page.page_id = ${p}revision.rev_page
177       AND
178        ${p}revision.rev_user = ${p}user.user_id
179       AND
180        ${p}revision.rev_text_id = ${p}text.old_id
181       AND
182        ( ${p}page.page_namespace <3
183         OR
184          ${p}page.page_namespace = 6
185         )
186      ORDER BY
187        ${p}page.page_namespace,
188        ${p}revision.rev_page,
189        ${p}revision.rev_id
190      ;
191    """).safe_substitute({
192        "p" : ""
193        })
194"""
195  Peruse these MediaWiki config file variables:
196 .  $wgDBprefix
197                                                                           """
198
199
200
201
202
203
204
205
206"""
207                  _
208                 (_)
209    ____   _____  _  ____     ____    ____   ___    ____   ____  _____  ____
210   |    \ (____ || ||  _ \   |  _ \  / ___) / _ \  / _  | / ___)(____ ||    \
211   | | | |/ ___ || || | | |  | |_| || |    | |_| |( (_| || |    / ___ || | | |
212   |_|_|_|\_____||_||_| |_|  |  __/ |_|     \___/  \___ ||_|    \_____||_|_|_|
213                             |_|                  (_____|                     
214
215                                                                           """
216
217def the_end():
218    db.close()
219    sys.exit()
220
221res = ()
222row = ()
223def set_row():
224    global res
225    global row
226    res = rs.fetch_row()
227    if res == ():
228        the_end()        ## !! This is the point at which we exit the program.
229    row = res[0]
230
231cur = ()
232ver = ()
233def reset_versioning():
234    global cur
235    global ver
236    cur = row[-1]
237    ver = 0
238
239db = _mysql.connect(
240     "localhost",
241     "wikiuser",
242     "wuwuwuwu",
243     "wikidb",
244     port=5432,
245     )
246"""
247  Peruse these MediaWiki config file variables:
248 .  $wgDBserver
249 .  $wgDBname
250 .  $wgDBuser
251 .  $wgDBpassword
252 .  $wgDBport
253                                                                           """
254
255db.query(query)
256rs = db.use_result()
257set_row()
258reset_versioning()
259while True:
260    while row[-1] == cur:
261        ver += 1
262        print row_writer(row[0:1] + (ver,) + row[1:])
263        set_row()
264    reset_versioning()
265