← Back to team overview

credativ team mailing list archive

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

 

Sandy Carter (http://www.savoirfairelinux.com) has proposed merging lp:~savoirfairelinux-openerp/openupgrade-addons/7.0 into lp:openupgrade-addons.

Requested reviews:
  OpenUpgrade Committers (openupgrade-committers)

For more details, see:
https://code.launchpad.net/~savoirfairelinux-openerp/openupgrade-addons/7.0/+merge/190413

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 Wiki.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_wiki.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.
-- 
https://code.launchpad.net/~savoirfairelinux-openerp/openupgrade-addons/7.0/+merge/190413
Your team OpenUpgrade Committers is requested to review the proposed merge of lp:~savoirfairelinux-openerp/openupgrade-addons/7.0 into lp:openupgrade-addons.
=== 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-10 16:19:03 +0000
@@ -0,0 +1,280 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    This module copyright (C) 2013 Savoir-faire Linux
+#    (<http://www.savoirfairelinux.com>).
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.openupgrade import openupgrade
+from openerp import pooler, SUPERUSER_ID
+
+
+def migrate_wiki_to_html(cr, pool):
+    document_page_obj = pool.get('document.page')
+    wiky = Wiky()
+    cr.execute("""\
+SELECT id, content
+FROM document_page
+WHERE content is not NULL;
+""")
+    for page_line_id, content in cr.fetchall():
+        document_page_obj.write(
+            cr, SUPERUSER_ID, [page_line_id],
+            {'content': wiky.process(content)}
+        )
+
+
+@openupgrade.migrate()
+def migrate(cr, version):
+    pool = pooler.get_pool(cr.dbname)
+    migrate_wiki_to_html(cr, pool)
+
+"""
+Wiky.py - Python library to converts Wiki MarkUp language to HTML.
+          Based on Wiki.js by Tanin Na Nakorn
+
+Copyright © 2013 Sandy Carter <bwrsandman@xxxxxxxxx>
+This work is free. You can redistribute it and/or modify it under the
+terms of the Creative Commons Attribution 3.0 Unported License.
+(http://creativecommons.org/licenses/by/3.0/legalcode)
+"""
+
+import re
+
+re_h3 = re.compile("^===[^=]+===$")
+re_h2 = re.compile("^==[^=]+==$")
+re_h1 = re.compile("^=[^=]+=$")
+re_indent = re.compile("^:+")
+re_hr = re.compile("^-{4}")
+re_ul = re.compile("^\*+ ")
+re_ol = re.compile("^#+ ")
+re_ul_ol = re.compile("^(\*+|#+) ")
+re_ul_li = re.compile("^(\*+|##+):? ")
+re_ol_li = re.compile("^(\*\*+|#+):? ")
+re_ul_ol_li = re.compile("^(\*+|#+):? ")
+re_youtube = re.compile("^(https?://)?(www\.)?youtube.com/(watch\?(.*)v=|embed/)([^&]+)")
+re_b_i = re.compile("'''''(([^']|([^']('{1,4})?[^']))+)'''''")
+re_b = re.compile("'''(([^']|([^'](''?)?[^']))+)'''")
+re_i = re.compile("''(([^']|([^']'?[^']))+)''")
+
+
+class Wiky:
+    def __init__(self, link_image=None):
+        self.link_image = link_image
+
+    def process(self, wikitext):
+        lines = wikitext.split("\n")
+        html = ""
+        i = 0
+        while i < len(lines):
+            line = lines[i]
+            if re_h3.match(line):
+                html += "<h3>%s</h3>" % line[3:-3]
+            elif re_h2.match(line):
+                html += "<h2>%s</h2>" % line[2:-2]
+            elif re_h1.match(line):
+                html += "<h1>%s</h1>" % line[1:-1]
+            elif re_hr.match(line):
+                html += "<hr/>"
+            elif re_indent.match(line):
+                start = i
+                while i < len(lines) and re_indent.match(lines[i]):
+                    i += 1
+                i -= 1
+                html += self.process_indent(lines[start: i + 1])
+            elif re_ul.match(line):
+                start = i
+                while i < len(lines) and re_ul_li.match(lines[i]):
+                    i += 1
+                i -= 1
+                html += self.process_bullet_point(lines[start: i + 1])
+            elif re_ol.match(line):
+                start = i
+                while i < len(lines) and re_ol_li.match(lines[i]):
+                    i += 1
+                i -= 1
+                html += self.process_bullet_point(lines[start: i + 1])
+            else :
+                html += self.process_normal(line)
+            html += "<br/>\n"
+            i += 1
+        return html
+
+    def process_indent(self, lines):
+        html = "\n<dl>\n"
+        i = 0
+        while i < len(lines):
+            line = lines[i]
+            html += "<dd>"
+            this_count = len(re_indent.match(line).group(0))
+            html += self.process_normal(line[this_count:])
+
+            nested_end = i
+            j = i + 1
+            while j < len(lines):
+                nested_count = len(re_indent.match(lines[j]).group(0))
+                if nested_count <= this_count:
+                    break
+                else:
+                    nested_end = j
+                j += 1
+
+            if nested_end > i:
+                html += self.process_indent(lines[i + 1: nested_end + 1])
+                i = nested_end
+
+            html += "</dd>\n"
+            i += 1
+        html += "</dl>\n"
+        return html
+
+    def process_bullet_point(self, lines):
+        if not len(lines):
+            return ""
+        html = "<ul>" if lines[0][0] == "*" else "<ol>"
+        html += '\n'
+        i = 0
+        while i < len(lines):
+            line = lines[i]
+            html += "<li>"
+            this_count = len(re_ul_ol.match(line).group(1))
+            html += self.process_normal(line[this_count+1:])
+
+            # continue previous with #:
+            nested_end = i
+            j = i + 1
+            while j < len(lines):
+                nested_count = len(re_ul_ol_li.match(lines[j]).group(1))
+                if nested_count < this_count:
+                    break
+                elif lines[j][nested_count] == ':':
+                    html += "<br/>" + self.process_normal(lines[j][nested_count + 2:])
+                    nested_end = j
+                else:
+                    break
+                j += 1
+            i = nested_end
+
+            # nested bullet point
+            nested_end = i
+            j = i + 1
+            while j < len(lines):
+                nested_count = len(re_ul_ol_li.match(lines[j]).group(1))
+                if nested_count <= this_count:
+                    break
+                else:
+                    nested_end = j
+                j += 1
+
+            if nested_end > i:
+                html += self.process_bullet_point(lines[i + 1: nested_end + 1])
+                i = nested_end
+
+            # continue previous with #:
+            nested_end = i
+            j = i + 1
+            while j < len(lines):
+                nested_count = len(re_ul_ol_li.match(lines[j]).group(1))
+                if nested_count < this_count:
+                    break
+                elif lines[j][nested_count] == ':':
+                    html += self.process_normal(lines[j][nested_count + 2:])
+                    nested_end = j
+                else:
+                    break
+                j += 1
+            i = nested_end
+            html += "</li>\n"
+            i += 1
+        html += "</ul>" if lines[0][0] == "*" else "</ol>"
+        html += '\n'
+        return html
+
+    def process_url(self, txt):
+        css = ('style="background: url(\"%s\") no-repeat scroll '
+               'right center transparent;padding-right: 13px;"'
+               % self.link_image) if self.link_image else ''
+        try:
+            index = txt.index(" ")
+            url = txt[:index]
+            label = txt[index + 1:]
+        except ValueError:
+            label = url = txt
+        return """<a href="%s" %s>%s</a>""" % (url, css, label)
+
+    @staticmethod
+    def process_image(txt):
+        try:
+            index = txt.index(" ")
+            url = txt[:index]
+            label = txt[index + 1:]
+        except ValueError:
+            url = txt
+            label = ""
+        return '<img src="%s" alt="%s" />' % (url, label)
+
+    @staticmethod
+    def process_video(url):
+        m = re_youtube.match(url)
+        if not m:
+            return "<b>%s is an invalid YouTube URL</b>" % url
+        url = "http://www.youtube.com/embed/"; + m.group(5)
+        return '<iframe width="480" height="390" src="%s" frameborder="0" allowfullscreen=""></iframe>' % url
+
+    def process_normal(self, wikitext):
+        # Image
+        while True:
+            try:
+                index = wikitext.index("[[File:")
+                end_index = wikitext.index("]]", index + 7)
+                wikitext = (wikitext[:index] +
+                            self.process_image(wikitext[index + 7:end_index]) +
+                            wikitext[end_index + 2:])
+            except ValueError:
+                break
+
+        # Video
+        while True:
+            try:
+                index = wikitext.index("[[Video:")
+                end_index = wikitext.index("]]", index + 8)
+                wikitext = (wikitext[:index] +
+                            self.process_video(wikitext[index+8:end_index]) +
+                            wikitext[end_index + 2:])
+            except ValueError:
+                break
+
+        # URL
+        for protocol in ["http","ftp","news"]:
+            end_index = -1
+            while True:
+                try:
+                    index = wikitext.index("[%s://" % protocol, end_index + 1)
+                    end_index = wikitext.index("]", index + len(protocol) + 4)
+                    wikitext = (wikitext[:index] +
+                                self.process_url(wikitext[index+1:end_index]) +
+                                wikitext[end_index+1:])
+                except ValueError:
+                    break
+
+        # Bold, Italics, Emphasis
+        wikitext = re_b_i.sub("<b><i>\g<1></i></b>", wikitext)
+        wikitext = re_b.sub("<b>\g<1></b>", wikitext)
+        wikitext = re_i.sub("<i>\g<1></i>", wikitext)
+
+        return wikitext

=== 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-10 16:19:03 +0000
@@ -0,0 +1,118 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    This module copyright (C) 2013 Savoir-faire Linux
+#    (<http://www.savoirfairelinux.com>).
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.openupgrade import openupgrade
+
+column_drops = [
+    ('wiki_wiki', 'tags'),
+    ('wiki_wiki', 'minor_edit'),
+    ('wiki_wiki', 'review'),
+    ('wiki_wiki', 'summary'),
+    ('wiki_wiki', 'toc'),
+    ('wiki_wiki', 'section'),
+    ('wiki_wiki_history', 'minor_edit'),
+]
+
+column_renames = {
+    'wiki_wiki': [
+        ('text_area', 'content'),
+    ],
+    'wiki_groups': [
+        ('template', 'content'),
+    ],
+    'wiki_wiki_history': [
+        ('text_area', 'content'),
+        ('wiki_id', 'page_id'),
+    ],
+}
+
+table_renames = [
+    ('wiki_wiki', 'document_page'),
+    ('wiki_wiki_history', 'document_page_history'),
+    ('wiki_create_menu', 'document_page_create_menu'),
+]
+
+model_renames = [
+    ('wiki.wiki', 'document.page'),
+]
+
+
+def precreate_type_content(cr):
+    """Pre-create the 'type' column with 'category' as the value"""
+    cr.execute("""\
+ALTER TABLE wiki_wiki ADD COLUMN type character varying;
+COMMENT ON COLUMN wiki_wiki.type IS 'Type';\
+""")
+    cr.execute("""UPDATE wiki_wiki SET type = 'content';""")
+
+
+def precreate_combine_wiki_groups_wiki_wiki(cr):
+    """Put wiki_wiki content into wiki_groups, then delete wiki_groups, conserve parent_id"""
+    cr.execute("""ALTER TABLE wiki_wiki ADD COLUMN old_id integer;""")
+    cr.execute("""\
+INSERT INTO wiki_wiki(create_uid, create_date, write_date, name, content, type, old_id)
+SELECT create_uid, create_date, write_date, name, content, 'category' AS type, id
+FROM wiki_groups
+ORDER BY id ASC;""")
+    cr.execute("""\
+UPDATE wiki_wiki w
+SET parent_id = (SELECT id FROM wiki_wiki WHERE old_id = w.group_id LIMIT 1)
+WHERE group_id IS NOT null;\
+""")
+    openupgrade.drop_columns(cr, [('wiki_wiki', 'group_id'), ('wiki_wiki', 'old_id')])
+
+
+def precreate_approver_gid(cr):
+    """Pre-create the 'approver_gid' column"""
+    cr.execute("""\
+ALTER TABLE document_page ADD COLUMN approver_gid integer;
+COMMENT ON COLUMN document_page.approver_gid IS 'Approver group';\
+""")
+    cr.execute("""\
+ALTER TABLE document_page
+  ADD CONSTRAINT document_page_approver_gid_fkey FOREIGN KEY (approver_gid)
+      REFERENCES res_groups (id) MATCH SIMPLE
+      ON UPDATE NO ACTION ON DELETE SET NULL;\
+""")
+
+
+def precreate_approval_required(cr):
+    """Pre-create the 'approval_required' column"""
+    cr.execute("""\
+ALTER TABLE document_page ADD COLUMN approval_required boolean;
+COMMENT ON COLUMN document_page.approval_required IS 'Require approval';\
+""")
+
+
+@openupgrade.migrate()
+def migrate(cr, version):
+    openupgrade.drop_columns(cr, column_drops)
+    openupgrade.rename_columns(cr, column_renames)
+    precreate_type_content(cr)
+    precreate_combine_wiki_groups_wiki_wiki(cr)
+    openupgrade.rename_tables(cr, table_renames)
+    openupgrade.rename_models(cr, model_renames)
+    precreate_approver_gid(cr)
+    precreate_approval_required(cr)
+    cr.execute("""DROP TABLE wiki_wiki_page_open;""")
+    cr.execute("""DROP TABLE wiki_make_index;""")
+    cr.execute("""DROP TABLE wiki_groups""")


Follow ups