Merge lp:~savoirfairelinux-openerp/openupgrade-addons/7.0 into lp:openupgrade-addons

Status: Merged
Merged at revision: 8143
Proposed branch: lp:~savoirfairelinux-openerp/openupgrade-addons/7.0
Merge into: lp:openupgrade-addons
Diff against target: 394 lines (+380/-0)
3 files modified
document_page/migrations/7.0.1.0.1/post-migration.py (+306/-0)
document_page/migrations/7.0.1.0.1/pre-migration.py (+60/-0)
document_page/migrations/7.0.1.0.1/user_notes.txt (+14/-0)
To merge this branch: bzr merge lp:~savoirfairelinux-openerp/openupgrade-addons/7.0
Reviewer Review Type Date Requested Status
Holger Brunn (Therp) code review Approve
Maxime Chambreuil (http://www.savoirfairelinux.com) (community) code review Approve
Sandy Carter (http://www.savoirfairelinux.com) (community) Approve
Stefan Rijnhart (Opener) Approve
Review via email: mp+190413@code.launchpad.net

Description of the change

Handling migration of wiki to document_page.

Groups turned into parent pages with type 'category'
Wiky syntax converted to html using specifically made python port of Wiky.js

Leftover from 6.1 after Upgrade:
 - Dashboards
 - OpenERP Web mobile
 - Process
 - web Dashboard

Missing from 7.0 after Upgrade:
 - Enterprise Process
 - View Editor

Lost data:
 - wiki_wiki.tags
 - wiki_wiki.minor_edit
 - wiki_wiki.review
 - wiki_wiki.summary
 - wiki_wiki.toc
 - wiki_wiki.section
 - wiki_wiki_history.minor_edit
 - wiki_groups.summary
 - wiki_make_index
 - wiki_wiki_page_open

Known issues:
  Views are messed up after upgrade, this is resolved by installing 'Enterprise Process' after the upgrade.

To post a comment you must log in.
Revision history for this message
Sylvain LE GAL (GRAP) (sylvain-legal) wrote :

I don't use neither know the 'wiki' module.
Sorry.

review: Abstain
Revision history for this message
Holger Brunn (Therp) (hbrunn) wrote :

Looks great! But this should be a migration script of the wiki module, not of the document_page module. So I'd advise to create an empty wiki addon that simply contains the script you developed. (and appropriate __openerp__.py, __init__.py of course)

Then on #343, #349, #408f, I think you need to copy data between the tables and not rename them

Please put the information about lost data into a file called user_notes.txt, the loang term goal is to present the information there to the user, giving a summary what points should be given attention.

When setting up your fake wiki module for 7.0, simply let it depend on Enterprise Process, then this addon will be installed automatically on upgrade.

review: Needs Fixing
Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Thanks for your contribution! I think the idea of rendering the wiki in Python is very elegant.

Holger, I think putting this script in the document_page module is very defendable. Looking at the code, it is clear that the document_page module is not only conceptually the replacement of the wiki module, but also a direct rewrite of it. This is actually already encoded in the base module's pre script that triggers the module renames.

The renaming of the tables and models (ll.343..352) goes together with this idea. Small fixes here: I think you do still need to rename the history model. You do not need to rename the create_menu table as this is a transient model.

I do not see why you would make such an effort to precreate and fill columns in the pre-script. Typically, this is done in the post-script. If it is to allow the orm to set a database constraint 'not null', remember that if you fill them properly in the post-script, the orm will set the constraint at the next, regular upgrade. Can you say if that was your main concern?

l.364: I am guessing the comment 'Put wiki_wiki content into wiki_groups' should be the other way around.

This module aggressively drops deprecated columns. I am generally in favour of prefixing them with the generated openupgrade prefix instead, to prevent unintentional loss of information. But pending the creation of the ephemeral service module to drop deprecated columns in a controlled fashion, I will not block this proposal for it.

review: Needs Fixing
Revision history for this message
Sandy Carter (http://www.savoirfairelinux.com) (sandy-carter) wrote :

Looking at the base migration script, I came to the conclusion that document_page was the simplified continuation of wiki_wiki. There is also the fact that modules that depened on wiki_wiki in 6.* now depend on document_page.

The issue with the views that was resolved by Enterprise process seems to be fixed.

I wasn't sure whether to put my precreate functions in pre, or post. That's fixed now.

What is the generated prefix? Is it version? How would you name it?

Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Hi Sandy, to retrieve the legacy name for columns or tables, you can use

    openupgrade.get_legacy_name(existing_table_or_column_name)

In rename_columns, you can specify (existing_column_name, None). That will call get_legacy_name internally.

Revision history for this message
Sandy Carter (http://www.savoirfairelinux.com) (sandy-carter) wrote :

This should address all your issues, Stefan.
Holger, I hope this works too.

review: Needs Resubmitting
Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Thanks for updating this branch! Code approved, but I think your comments in user_notes.txt about leftover modules, missing modules and known issues are a little off. For instance, the Process module in 6.1 is the same module as the Enterprice process in 7.0, and it will always be installed. Could you perhaps just remove these three comments and keep the first two lines of the file and the lost data stanza?

I think the issue you are experiencing with the views after the upgrade may be similar to https://bugs.launchpad.net/openupgrade-server/+bug/1226086, which fixed itself after the next (regular) module upgrade.

review: Needs Fixing
Revision history for this message
Sandy Carter (http://www.savoirfairelinux.com) (sandy-carter) wrote :

Done

Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Approved. Thanks again!

review: Approve
Revision history for this message
Sandy Carter (http://www.savoirfairelinux.com) (sandy-carter) :
review: Approve
Revision history for this message
Maxime Chambreuil (http://www.savoirfairelinux.com) (max3903) wrote :

lgtm

review: Approve (code review)
Revision history for this message
Holger Brunn (Therp) (hbrunn) :
review: Approve (code review)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'document_page/migrations/7.0.1.0.1/post-migration.py'
--- document_page/migrations/7.0.1.0.1/post-migration.py 1970-01-01 00:00:00 +0000
+++ document_page/migrations/7.0.1.0.1/post-migration.py 2013-10-15 19:37:17 +0000
@@ -0,0 +1,306 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# OpenERP, Open Source Management Solution
5# This module copyright (C) 2013 Savoir-faire Linux
6# (<http://www.savoirfairelinux.com>).
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23from openerp.openupgrade import openupgrade
24from openerp import pooler, SUPERUSER_ID
25from openerp.openupgrade.openupgrade import logged_query
26
27
28def combine_wiki_groups_document_page(cr):
29 """Put wiki_groups content into wiki_wiki, then delete wiki_groups, conserve parent_id"""
30 logged_query(cr, """ALTER TABLE document_page ADD COLUMN old_id integer;""")
31 logged_query(cr, """\
32INSERT INTO document_page(create_uid, create_date, write_date, name, content, type, old_id)
33SELECT create_uid, create_date, write_date, name, content, 'category' AS type, id
34FROM wiki_groups
35ORDER BY id ASC;""")
36 logged_query(cr, """\
37UPDATE document_page w
38SET parent_id = (SELECT id FROM document_page WHERE old_id = w.group_id LIMIT 1)
39WHERE group_id IS NOT null;\
40""")
41 openupgrade.drop_columns(cr, [('document_page', 'group_id'), ('document_page', 'old_id')])
42
43
44def migrate_wiki_to_html(cr, pool):
45 document_page_obj = pool.get('document.page')
46 wiky = Wiky()
47 logged_query(cr, """\
48SELECT id, content
49FROM document_page
50WHERE content is not NULL;
51""")
52 for page_line_id, content in cr.fetchall():
53 document_page_obj.write(
54 cr, SUPERUSER_ID, [page_line_id],
55 {'content': wiky.process(content)}
56 )
57
58
59@openupgrade.migrate()
60def migrate(cr, version):
61 pool = pooler.get_pool(cr.dbname)
62 combine_wiki_groups_document_page(cr)
63 migrate_wiki_to_html(cr, pool)
64 logged_query(cr, """DROP TABLE wiki_wiki_page_open;""")
65 logged_query(cr, """DROP TABLE wiki_make_index;""")
66 logged_query(cr, """DROP TABLE wiki_create_menu""")
67 logged_query(cr, """DROP TABLE wiki_groups""")
68
69
70##############################################################################
71#
72# Wiky.py - Python library to converts Wiki MarkUp language to HTML.
73# Based on Wiki.js by Tanin Na Nakorn
74#
75# Copyright © 2013 Sandy Carter <bwrsandman@gmail.com>
76# This work is free. You can redistribute it and/or modify it under the
77# terms of the Creative Commons Attribution 3.0 Unported License.
78# (http://creativecommons.org/licenses/by/3.0/legalcode)
79#
80##############################################################################
81
82import re
83
84re_h3 = re.compile("^===[^=]+===$")
85re_h2 = re.compile("^==[^=]+==$")
86re_h1 = re.compile("^=[^=]+=$")
87re_indent = re.compile("^:+")
88re_hr = re.compile("^-{4}")
89re_ul = re.compile("^\*+ ")
90re_ol = re.compile("^#+ ")
91re_ul_ol = re.compile("^(\*+|#+) ")
92re_ul_li = re.compile("^(\*+|##+):? ")
93re_ol_li = re.compile("^(\*\*+|#+):? ")
94re_ul_ol_li = re.compile("^(\*+|#+):? ")
95re_youtube = re.compile("^(https?://)?(www\.)?youtube.com/(watch\?(.*)v=|embed/)([^&]+)")
96re_b_i = re.compile("'''''(([^']|([^']('{1,4})?[^']))+)'''''")
97re_b = re.compile("'''(([^']|([^'](''?)?[^']))+)'''")
98re_i = re.compile("''(([^']|([^']'?[^']))+)''")
99
100
101class Wiky:
102 def __init__(self, link_image=None):
103 self.link_image = link_image
104
105 def process(self, wikitext):
106 lines = wikitext.split("\n")
107 html = ""
108 i = 0
109 while i < len(lines):
110 line = lines[i]
111 if re_h3.match(line):
112 html += "<h3>%s</h3>" % line[3:-3]
113 elif re_h2.match(line):
114 html += "<h2>%s</h2>" % line[2:-2]
115 elif re_h1.match(line):
116 html += "<h1>%s</h1>" % line[1:-1]
117 elif re_hr.match(line):
118 html += "<hr/>"
119 elif re_indent.match(line):
120 start = i
121 while i < len(lines) and re_indent.match(lines[i]):
122 i += 1
123 i -= 1
124 html += self.process_indent(lines[start: i + 1])
125 elif re_ul.match(line):
126 start = i
127 while i < len(lines) and re_ul_li.match(lines[i]):
128 i += 1
129 i -= 1
130 html += self.process_bullet_point(lines[start: i + 1])
131 elif re_ol.match(line):
132 start = i
133 while i < len(lines) and re_ol_li.match(lines[i]):
134 i += 1
135 i -= 1
136 html += self.process_bullet_point(lines[start: i + 1])
137 else:
138 html += self.process_normal(line)
139 html += "<br/>\n"
140 i += 1
141 return html
142
143 def process_indent(self, lines):
144 html = "\n<dl>\n"
145 i = 0
146 while i < len(lines):
147 line = lines[i]
148 html += "<dd>"
149 this_count = len(re_indent.match(line).group(0))
150 html += self.process_normal(line[this_count:])
151
152 nested_end = i
153 j = i + 1
154 while j < len(lines):
155 nested_count = len(re_indent.match(lines[j]).group(0))
156 if nested_count <= this_count:
157 break
158 else:
159 nested_end = j
160 j += 1
161
162 if nested_end > i:
163 html += self.process_indent(lines[i + 1: nested_end + 1])
164 i = nested_end
165
166 html += "</dd>\n"
167 i += 1
168 html += "</dl>\n"
169 return html
170
171 def process_bullet_point(self, lines):
172 if not len(lines):
173 return ""
174 html = "<ul>" if lines[0][0] == "*" else "<ol>"
175 html += '\n'
176 i = 0
177 while i < len(lines):
178 line = lines[i]
179 html += "<li>"
180 this_count = len(re_ul_ol.match(line).group(1))
181 html += self.process_normal(line[this_count+1:])
182
183 # continue previous with #:
184 nested_end = i
185 j = i + 1
186 while j < len(lines):
187 nested_count = len(re_ul_ol_li.match(lines[j]).group(1))
188 if nested_count < this_count:
189 break
190 elif lines[j][nested_count] == ':':
191 html += "<br/>" + self.process_normal(lines[j][nested_count + 2:])
192 nested_end = j
193 else:
194 break
195 j += 1
196 i = nested_end
197
198 # nested bullet point
199 nested_end = i
200 j = i + 1
201 while j < len(lines):
202 nested_count = len(re_ul_ol_li.match(lines[j]).group(1))
203 if nested_count <= this_count:
204 break
205 else:
206 nested_end = j
207 j += 1
208
209 if nested_end > i:
210 html += self.process_bullet_point(lines[i + 1: nested_end + 1])
211 i = nested_end
212
213 # continue previous with #:
214 nested_end = i
215 j = i + 1
216 while j < len(lines):
217 nested_count = len(re_ul_ol_li.match(lines[j]).group(1))
218 if nested_count < this_count:
219 break
220 elif lines[j][nested_count] == ':':
221 html += self.process_normal(lines[j][nested_count + 2:])
222 nested_end = j
223 else:
224 break
225 j += 1
226 i = nested_end
227 html += "</li>\n"
228 i += 1
229 html += "</ul>" if lines[0][0] == "*" else "</ol>"
230 html += '\n'
231 return html
232
233 def process_url(self, txt):
234 css = ('style="background: url(\"%s\") no-repeat scroll '
235 'right center transparent;padding-right: 13px;"'
236 % self.link_image) if self.link_image else ''
237 try:
238 index = txt.index(" ")
239 url = txt[:index]
240 label = txt[index + 1:]
241 except ValueError:
242 label = url = txt
243 return """<a href="%s" %s>%s</a>""" % (url, css, label)
244
245 @staticmethod
246 def process_image(txt):
247 try:
248 index = txt.index(" ")
249 url = txt[:index]
250 label = txt[index + 1:]
251 except ValueError:
252 url = txt
253 label = ""
254 return '<img src="%s" alt="%s" />' % (url, label)
255
256 @staticmethod
257 def process_video(url):
258 m = re_youtube.match(url)
259 if not m:
260 return "<b>%s is an invalid YouTube URL</b>" % url
261 url = "http://www.youtube.com/embed/" + m.group(5)
262 return '<iframe width="480" height="390" src="%s" frameborder="0" allowfullscreen=""></iframe>' % url
263
264 def process_normal(self, wikitext):
265 # Image
266 while True:
267 try:
268 index = wikitext.index("[[File:")
269 end_index = wikitext.index("]]", index + 7)
270 wikitext = (wikitext[:index] +
271 self.process_image(wikitext[index + 7:end_index]) +
272 wikitext[end_index + 2:])
273 except ValueError:
274 break
275
276 # Video
277 while True:
278 try:
279 index = wikitext.index("[[Video:")
280 end_index = wikitext.index("]]", index + 8)
281 wikitext = (wikitext[:index] +
282 self.process_video(wikitext[index+8:end_index]) +
283 wikitext[end_index + 2:])
284 except ValueError:
285 break
286
287 # URL
288 for protocol in ["http", "ftp", "news"]:
289 end_index = -1
290 while True:
291 try:
292 index = wikitext.index("[%s://" % protocol, end_index + 1)
293 end_index = wikitext.index("]", index + len(protocol) + 4)
294 wikitext = (wikitext[:index] +
295 self.process_url(wikitext[index+1:end_index]) +
296 wikitext[end_index+1:])
297 except ValueError:
298 break
299
300 # Bold, Italics, Emphasis
301 wikitext = re_b_i.sub("<b><i>\1</i></b>", wikitext)
302 wikitext = re_b.sub("<b>\1</b>", wikitext)
303 wikitext = re_i.sub("<i>\1</i>", wikitext)
304
305 return wikitext
306# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
0307
=== added file 'document_page/migrations/7.0.1.0.1/pre-migration.py'
--- document_page/migrations/7.0.1.0.1/pre-migration.py 1970-01-01 00:00:00 +0000
+++ document_page/migrations/7.0.1.0.1/pre-migration.py 2013-10-15 19:37:17 +0000
@@ -0,0 +1,60 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# OpenERP, Open Source Management Solution
5# This module copyright (C) 2013 Savoir-faire Linux
6# (<http://www.savoirfairelinux.com>).
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23from openerp.openupgrade import openupgrade
24
25column_renames = {
26 'wiki_wiki': [
27 ('text_area', 'content'),
28 ('tags', None),
29 ('minor_edit', None),
30 ('review', None),
31 ('summary', None),
32 ('toc', None),
33 ('section', None),
34 ],
35 'wiki_groups': [
36 ('template', 'content'),
37 ],
38 'wiki_wiki_history': [
39 ('text_area', 'content'),
40 ('wiki_id', 'page_id'),
41 ('minor_edit', None),
42 ],
43}
44
45table_renames = [
46 ('wiki_wiki', 'document_page'),
47 ('wiki_wiki_history', 'document_page_history'),
48]
49
50model_renames = [
51 ('wiki.wiki', 'document.page'),
52 ('wiki.wiki.history', 'document.page.history'),
53]
54
55
56@openupgrade.migrate()
57def migrate(cr, version):
58 openupgrade.rename_columns(cr, column_renames)
59 openupgrade.rename_tables(cr, table_renames)
60 openupgrade.rename_models(cr, model_renames)
061
=== added file 'document_page/migrations/7.0.1.0.1/user_notes.txt'
--- document_page/migrations/7.0.1.0.1/user_notes.txt 1970-01-01 00:00:00 +0000
+++ document_page/migrations/7.0.1.0.1/user_notes.txt 2013-10-15 19:37:17 +0000
@@ -0,0 +1,14 @@
1Groups turned into parent pages with type 'category'
2Wiky syntax converted to html using specifically made python port of Wiky.js
3
4Lost data:
5 - wiki_wiki.tags
6 - wiki_wiki.minor_edit
7 - wiki_wiki.review
8 - wiki_wiki.summary
9 - wiki_wiki.toc
10 - wiki_wiki.section
11 - wiki_wiki_history.minor_edit
12 - wiki_groups.summary
13 - wiki_make_index
14 - wiki_wiki_page_open

Subscribers

People subscribed via source and target branches