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