Valentin Lab has proposed merging lp:~0k.io/openupgrade-server/8.0-openupgrade-records-2 into lp:openupgrade-server/8.0.
Requested reviews: Stefan Rijnhart (Therp) (stefan-therp) For more details, see: https://code.launchpad.net/~0k.io/openupgrade-server/8.0-openupgrade-records-2/+merge/214768 This commit contains all the file of the ``openupgrade_records`` module. You won't find the core or the doc code here, this was split up in: core: https://code.launchpad.net/~0k.io/openupgrade-server/8.0-openupgrade-base-2 docs: https://code.launchpad.net/~0k.io/openupgrade-server/8.0-openupgrade-doc-2 -- https://code.launchpad.net/~0k.io/openupgrade-server/8.0-openupgrade-records-2/+merge/214768 Your team OpenUpgrade Committers is subscribed to branch lp:openupgrade-server/8.0.
=== added directory 'openerp/addons/openupgrade_records' === added file 'openerp/addons/openupgrade_records/__init__.py' --- openerp/addons/openupgrade_records/__init__.py 1970-01-01 00:00:00 +0000 +++ openerp/addons/openupgrade_records/__init__.py 2014-04-08 14:03:57 +0000 @@ -0,0 +1,2 @@ +import model +import lib === added file 'openerp/addons/openupgrade_records/__openerp__.py' --- openerp/addons/openupgrade_records/__openerp__.py 1970-01-01 00:00:00 +0000 +++ openerp/addons/openupgrade_records/__openerp__.py 2014-04-08 14:03:57 +0000 @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module Copyright (C) 2012 OpenUpgrade community +# https://launchpad.net/~openupgrade-committers +# +# Contributors: +# Therp BV <http://therp.nl> +# +# 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/>. +# +############################################################################## + + +{ + 'name': 'OpenUpgrade Records', + 'version': '0.2', + 'category': 'Normal', + 'description': """Allow OpenUpgrade records to be +stored in the database and compare with other servers. + +This module depends on OpenERP client lib: + + easy_install openerp-client-lib + +""", + 'author': 'OpenUpgrade Community', + 'maintainer': 'OpenUpgrade Community', + 'contributors': ['Therp BV'], + 'website': 'https://launchpad.net/~openupgrade-committers', + 'depends': [], + 'init_xml': [], + 'update_xml': [ + 'view/openupgrade_record.xml', + 'view/comparison_config.xml', + 'view/analysis_wizard.xml', + 'view/generate_records_wizard.xml', + 'view/install_all_wizard.xml', + 'security/ir.model.access.csv', + ], + 'demo_xml': [ + ], + 'test': [ + ], + 'installable': True, + 'auto_install': False, + 'external_dependencies': { + 'python' : ['openerplib'], + }, +} +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: === added file 'openerp/addons/openupgrade_records/__terp__.py' --- openerp/addons/openupgrade_records/__terp__.py 1970-01-01 00:00:00 +0000 +++ openerp/addons/openupgrade_records/__terp__.py 2014-04-08 14:03:57 +0000 @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module Copyright (C) 2012 OpenUpgrade community +# https://launchpad.net/~openupgrade-committers +# +# Contributors: +# Therp BV <http://therp.nl> +# +# 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/>. +# +############################################################################## + + +{ + 'name': 'OpenUpgrade Records', + 'version': '0.2', + 'category': 'Normal', + 'description': """Allow OpenUpgrade records to be +stored in the database and compare with other servers. + +This module depends on OpenERP client lib: + + easy_install openerp-client-lib + +""", + 'author': 'OpenUpgrade Community', + 'maintainer': 'OpenUpgrade Community', + 'contributors': ['Therp BV'], + 'website': 'https://launchpad.net/~openupgrade-committers', + 'depends': [], + 'init_xml': [], + 'update_xml': [ + 'view/openupgrade_record.xml', + 'view/comparison_config.xml', + 'view/analysis_wizard.xml', + 'view/generate_records_wizard.xml', + 'view/install_all_wizard.xml', + 'security/ir.model.access.csv', + ], + 'demo_xml': [ + ], + 'test': [ + ], + 'installable': True, + 'auto_install': False, + 'external_dependencies': { + 'python' : ['openerplib'], + }, +} +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: === added directory 'openerp/addons/openupgrade_records/lib' === added file 'openerp/addons/openupgrade_records/lib/__init__.py' --- openerp/addons/openupgrade_records/lib/__init__.py 1970-01-01 00:00:00 +0000 +++ openerp/addons/openupgrade_records/lib/__init__.py 2014-04-08 14:03:57 +0000 @@ -0,0 +1,2 @@ +import apriori +import compare === added file 'openerp/addons/openupgrade_records/lib/apriori.py' --- openerp/addons/openupgrade_records/lib/apriori.py 1970-01-01 00:00:00 +0000 +++ openerp/addons/openupgrade_records/lib/apriori.py 2014-04-08 14:03:57 +0000 @@ -0,0 +1,14 @@ +""" Encode any known changes to the database here +to help the matching process +""" + +renamed_modules = { + 'account_coda': 'l10n_be_coda', + 'base_crypt': 'auth_crypt', + 'mrp_subproduct': 'mrp_byproduct', + 'users_ldap': 'auth_ldap', + 'wiki': 'document_page', + } + +renamed_models = { + } === added file 'openerp/addons/openupgrade_records/lib/compare.py' --- openerp/addons/openupgrade_records/lib/compare.py 1970-01-01 00:00:00 +0000 +++ openerp/addons/openupgrade_records/lib/compare.py 2014-04-08 14:03:57 +0000 @@ -0,0 +1,250 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2011 Therp BV (<http://therp.nl>). +# +# 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/>. +# +############################################################################## + +##################################################################### +# library providing a function to analyse two progressive database +# layouts from the OpenUpgrade server. +##################################################################### + +import copy + +try: + from openerp.addons.openupgrade_records.lib import apriori +except ImportError: + from openupgrade_records.lib import apriori + +keys = [ + 'module', + 'mode', + 'model', + 'field', + 'type', + 'isfunction', + 'relation', + 'required', + 'selection_keys', + 'req_default', + 'inherits', + ] + +def module_map(module): + return apriori.renamed_modules.get( + module, module) + +def compare_records(dict_old, dict_new, fields): + """ + Check equivalence of two OpenUpgrade field representations + with respect to the keys in the 'fields' arguments. + Take apriori knowledge into account for mapped modules or + model names. + Return True of False. + """ + for field in fields: + if field == 'module': + if (module_map(dict_old[field]) != dict_new[field]): + return False + elif field == 'model': + if (apriori.renamed_models.get( + dict_old[field], dict_old[field]) != dict_new[field]): + return False + else: + if dict_old[field] != dict_new[field]: + return False + return True + +def search(item, item_list, fields): + """ + Find a match of a dictionary in a list of similar dictionaries + with respect to the keys in the 'fields' arguments. + Return the item if found or None. + """ + for i in item_list: + if not compare_records(item, i, fields): + continue + return i + return None + +def fieldprint(old, new, field, text, reprs): + fieldrepr = "%s (%s)" % (old['field'], old['type']) + repr = '%s / %s / %s' % ( + old['module'].ljust(12), old['model'].ljust(24), fieldrepr.ljust(30)) + if text: + reprs.setdefault(module_map(old['module']), []).append( + "%s: %s" % (repr, text)) + else: + reprs.setdefault(module_map(old['module']), []).append( + "%s: %s is now \'%s\' ('%s')" % ( + repr, field, new[field], old[field])) + +def report_generic(new, old, attrs, reprs): + for attr in attrs: + if attr == 'required': + if old[attr] != new['required'] and new['required']: + text = "now required" + if new['req_default']: + text += ', default = %s' % new['req_default'] + fieldprint(old, new, None, text, reprs) + elif attr == 'isfunction': + if old['isfunction'] != new['isfunction']: + if new['isfunction']: + text = "now a function" + else: + text = "not a function anymore" + fieldprint(old, new, None, text, reprs) + else: + if old[attr] != new[attr]: + fieldprint(old, new, attr, None, reprs) + +def compare_sets(old_records, new_records): + """ + Compare a set of OpenUpgrade field representations. + Try to match the equivalent fields in both sets. + Return a textual representation of changes in a dictionary with + module names as keys. Special case is the 'general' key + which contains overall remarks and matching statistics. + """ + reprs = {'general': []} + + for record in old_records + new_records: + record['matched'] = False + origlen = len(old_records) + new_models = set([ column['model'] for column in new_records ]) + old_models = set([ column['model'] for column in old_records ]) + + matched_direct = 0 + matched_other_module = 0 + matched_other_type = 0 + matched_other_name = 0 + in_obsolete_models = 0 + + obsolete_models = [] + for model in old_models: + if model not in new_models: + obsolete_models.append(model) + reprs['general'].append('obsolete model %s' % model) + + for column in copy.copy(old_records): + if column['model'] in obsolete_models: + old_records.remove(column) + in_obsolete_models += 1 + + for model in new_models: + if model not in old_models: + reprs['general'].append('new model %s' % model) + + def match(match_fields, report_fields, warn=False): + count = 0 + for column in copy.copy(old_records): + found = search(column, new_records, match_fields) + if found: + if warn: + pass + #print "Tentatively" + report_generic(found, column, report_fields, reprs) + old_records.remove(column) + new_records.remove(found) + count += 1 + return count + + matched_direct = match( + ['module', 'mode', 'model', 'field'], + ['relation', 'type', 'selection_keys', 'inherits', 'isfunction', 'required']) + + # other module, same type and operation + matched_other_module = match( + ['mode', 'model', 'field', 'type'], + ['module', 'relation', 'selection_keys', 'inherits', 'isfunction', 'required']) + + # other module, same operation, other type + matched_other_type = match( + ['mode', 'model', 'field'], + ['relation', 'type', 'selection_keys', 'inherits', 'isfunction', 'required']) + + # fields with other names + #matched_other_name = match( + # ['module', 'type', 'relation'], + # ['field', 'relation', 'type', 'selection_keys', + # 'inherits', 'isfunction', 'required'], warn=True) + + printkeys = [ + 'relation', 'required', 'selection_keys', + 'req_default', 'inherits', 'mode' + ] + for column in old_records: + # we do not care about removed function fields + if not column['isfunction']: + if column['mode'] == 'create': + column['mode'] = '' + fieldprint( + column, None, None, "DEL " + ", ".join( + [k + ': ' + str(column[k]) for k in printkeys if column[k]] + ), reprs) + + for column in new_records: + # we do not care about newly added function fields + if not column['isfunction']: + if column['mode'] == 'create': + column['mode'] = '' + fieldprint( + column, None, None, "NEW " + ", ".join( + [k + ': ' + str(column[k]) for k in printkeys if column[k]] + ), reprs) + + for line in [ + "# %d fields matched," % (origlen - len(old_records)), + "# Direct match: %d" % matched_direct, + "# Found in other module: %d" % matched_other_module, + "# Found with different type: %d" % matched_other_type, + "# Found with different name: %d" % matched_other_name, + "# In obsolete models: %d" % in_obsolete_models, + "# Not matched: %d" % len(old_records), + "# New columns: %d" % len(new_records), + ]: + reprs['general'].append(line) + return reprs + +def compare_xml_sets(old_records, new_records): + reprs = {} + match_fields = ['module', 'model', 'name'] + for column in copy.copy(old_records): + found = search(column, new_records, match_fields) + if found: + old_records.remove(column) + new_records.remove(found) + + for record in old_records: + record['old'] = True + for record in new_records: + record['new'] = True + + sorted_records = sorted( + old_records + new_records, + key=lambda k: '%s%s%s' % (k['model'].ljust(128), 'old' in k, k['name']) + ) + for entry in sorted_records: + if 'old' in entry: + content = 'DEL %s: %s' % (entry['model'], + entry['name']) + elif 'new' in entry: + content = 'NEW %s: %s' % (entry['model'], + entry['name']) + reprs.setdefault(module_map(entry['module']), []).append(content) + return reprs === added directory 'openerp/addons/openupgrade_records/model' === added file 'openerp/addons/openupgrade_records/model/__init__.py' --- openerp/addons/openupgrade_records/model/__init__.py 1970-01-01 00:00:00 +0000 +++ openerp/addons/openupgrade_records/model/__init__.py 2014-04-08 14:03:57 +0000 @@ -0,0 +1,6 @@ +import openupgrade_record +import comparison_config +import analysis_wizard +import generate_records_wizard +import install_all_wizard + === added file 'openerp/addons/openupgrade_records/model/analysis_wizard.py' --- openerp/addons/openupgrade_records/model/analysis_wizard.py 1970-01-01 00:00:00 +0000 +++ openerp/addons/openupgrade_records/model/analysis_wizard.py 2014-04-08 14:03:57 +0000 @@ -0,0 +1,181 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module Copyright (C) 2012 OpenUpgrade community +# https://launchpad.net/~openupgrade-committers +# +# Contributors: +# Therp BV <http://therp.nl> +# +# 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/>. +# +############################################################################## + +import os +from openerp.osv import osv, fields + +try: + from openerp.addons.openupgrade_records.lib import compare + from openerp.addons.openupgrade_records.lib import apriori + from openerp.addons import get_module_path +except ImportError: + from openupgrade_records.lib import compare + from openupgrade_records.lib import apriori + from addons import get_module_path + +class openupgrade_analysis_wizard(osv.osv_memory): + _name = 'openupgrade.analysis.wizard' + _description = 'OpenUpgrade Analysis Wizard' + _columns = { + 'server_config': fields.many2one( + 'openupgrade.comparison.config', + 'Configuration', required=True), + 'state': fields.selection( + [('init', 'Init'), ('ready', 'Ready')], 'State', + readonly=True), + 'log': fields.text('Log'), + 'write': fields.boolean( + 'Write files', + help='Write analysis files to the module directories' + ), + } + _defaults = { + 'state': lambda *a: 'init', + 'write': lambda *a: True, + } + + def get_communication(self, cr, uid, ids, context=None): + """ + Retrieve both sets of database representations, + perform the comparison and register the resulting + change set + """ + def write_file( + module, version, contents, filename='openupgrade_analysis.txt'): + module_path = get_module_path(module) + if not module_path: + return "ERROR: could not find module path:\n" + full_path = os.path.join( + module_path, 'migrations', version) + if not os.path.exists(full_path): + try: + os.makedirs(full_path) + except os.error: + return "ERROR: could not create migrations directory:\n" + logfile = os.path.join(full_path, filename) + try: + f = open(logfile, 'w') + except Exception: + return "ERROR: could not open file %s for writing:\n" % logfile + f.write(contents) + f.close() + return None + + wizard = self.browse(cr, uid, ids[0], context=context) + # Retrieve connection and access methods + conf_obj = self.pool.get('openupgrade.comparison.config') + connection = conf_obj.get_connection( + cr, uid, [wizard.server_config.id], context=context) + remote_record_obj = connection.get_model('openupgrade.record') + local_record_obj = self.pool.get('openupgrade.record') + + # Retrieve field representations and compare + remote_records = remote_record_obj.field_dump(context) + local_records = local_record_obj.field_dump(cr, uid, context) + modules_record = set([record['module'] for record in remote_records + local_records]) + res = compare.compare_sets(remote_records, local_records) + + # Retrieve xml id representations and compare + fields = ['module', 'model', 'name'] + local_xml_record_ids = local_record_obj.search( + cr, uid, [('type', '=', 'xmlid')]) + remote_xml_record_ids = remote_record_obj.search( + [('type', '=', 'xmlid')]) + local_xml_records = [ + dict([(field, x[field]) for field in fields]) + for x in local_record_obj.read( + cr, uid, local_xml_record_ids, fields) + ] + remote_xml_records = [ + dict([(field, x[field]) for field in fields]) + for x in remote_record_obj.read( + remote_xml_record_ids, fields) + ] + modules_xml_records = set([record['module'] for record in remote_xml_records + local_xml_records]) + res_xml = compare.compare_xml_sets( + remote_xml_records, local_xml_records) + + # reorder and output the result + keys = ['general'] + list(modules_record & modules_xml_records) + module_obj = self.pool.get('ir.module.module') + module_ids = module_obj.search( + cr, uid, [('state', '=', 'installed')]) + modules = dict([(x['name'], x) for x in module_obj.read(cr, uid, module_ids)]) + general = '' + for key in keys: + contents = "---Fields in module '%s'---\n" % key + if key in res: + contents += '\n'.join([unicode(line) for line in sorted(res[key])]) + if res[key]: + contents += '\n' + contents += "---XML records in module '%s'---\n" % key + if key in res_xml: + contents += '\n'.join([unicode(line) for line in res_xml[key]]) + if res_xml[key]: + contents += '\n' + if key not in res and key not in res_xml: + contents += '-- nothing has changed in this module' + if key == 'general': + general += contents + continue + if key not in modules: + general += ( + "ERROR: module not in list of installed modules:\n" + + contents) + continue + if wizard.write: + error = write_file( + key, modules[key]['installed_version'], contents) + if error: + general += error + general += contents + else: + general += contents + + # Store the general log in as many places as possible ;-) + if wizard.write and 'base' in modules: + write_file( + 'base', modules['base']['installed_version'], general, + 'openupgrade_general_log.txt') + self.pool.get('openupgrade.comparison.config').write( + cr, uid, wizard.server_config.id, + {'last_log': general}) + self.write(cr, uid, ids, {'state': 'ready', 'log': general}) + + result = { + 'name': self._description, + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'openupgrade.analysis.wizard', + 'domain': [], + 'context': context, + 'type': 'ir.actions.act_window', + #'target': 'new', + 'res_id': ids[0], + } + return result + +openupgrade_analysis_wizard() + === added file 'openerp/addons/openupgrade_records/model/comparison_config.py' --- openerp/addons/openupgrade_records/model/comparison_config.py 1970-01-01 00:00:00 +0000 +++ openerp/addons/openupgrade_records/model/comparison_config.py 2014-04-08 14:03:57 +0000 @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module Copyright (C) 2012 OpenUpgrade community +# https://launchpad.net/~openupgrade-committers +# +# Contributors: +# Therp BV <http://therp.nl> +# +# 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.osv import osv, fields +import openerplib +from openerp.tools.translate import _ + +class openupgrade_comparison_config(osv.osv): + _name = 'openupgrade.comparison.config' + _columns = { + 'name': fields.char('Name', size=64), + 'server': fields.char('Server', size=64, required=True), + 'port': fields.integer('Port', required=True), + 'protocol': fields.selection( + [('http://', 'XML-RPC')], + # ('https://', 'XML-RPC Secure')], not supported by libopenerp + 'Protocol', required=True), + 'database': fields.char('Database', size=64, required=True), + 'username': fields.char('Username', size=24, required=True), + 'password': fields.char('Password', size=24, required=True, password=True), + 'last_log': fields.text('Last log'), + } + _defaults = { + 'port': lambda *a: 8069, + 'protocol': lambda *a: 'http://', + } + + def get_connection(self, cr, uid, ids, context=None): + if not ids: + raise osv.except_osv( + _("Cannot connect"), _("Invalid id passed.")) + conf = self.read(cr, uid, ids[0], context=None) + return openerplib.get_connection( + hostname=conf['server'], + database=conf['database'], + login=conf['username'], + password=conf['password'], + port=conf['port'], + ) + + def test_connection(self, cr, uid, ids, context=None): + try: + connection = self.get_connection(cr, uid, [ids[0]], context) + user_model = connection.get_model("res.users") + ids = user_model.search([("login", "=", "admin")]) + user_info = user_model.read(ids[0], ["name"]) + except Exception, e: + raise osv.except_osv( + _("Connection failed."), unicode(e)) + raise osv.except_osv( + _("Connection succesful."), + _("%s is connected.") % user_info["name"] + ) + + def analyze(self, cr, uid, ids, context=None): + """ + Run the analysis wizard + """ + wizard_obj = self.pool.get('openupgrade.analysis.wizard') + wizard_id = wizard_obj.create( + cr, uid, {'server_config': ids[0]}, context) + result = { + 'name': wizard_obj._description, + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'openupgrade.analysis.wizard', + 'domain': [], + 'context': context, + 'type': 'ir.actions.act_window', + 'target': 'new', + 'res_id': wizard_id, + 'nodestroy': True, + } + return result + +openupgrade_comparison_config() === added file 'openerp/addons/openupgrade_records/model/generate_records_wizard.py' --- openerp/addons/openupgrade_records/model/generate_records_wizard.py 1970-01-01 00:00:00 +0000 +++ openerp/addons/openupgrade_records/model/generate_records_wizard.py 2014-04-08 14:03:57 +0000 @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module Copyright (C) 2012 OpenUpgrade community +# https://launchpad.net/~openupgrade-committers +# +# Contributors: +# Therp BV <http://therp.nl> +# +# 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/>. +# +############################################################################## + +import os +from openerp.osv import osv, fields +from openerp import pooler +try: + from openerp.openupgrade import openupgrade_tools +except ImportError: + from openupgrade import openupgrade_tools + +class generate_records_wizard(osv.osv_memory): + _name = 'openupgrade.generate.records.wizard' + _description = 'OpenUpgrade Generate Records Wizard' + _columns = { + 'state': fields.selection([('init', 'init'), ('ready', 'ready')], 'State'), + } + _defaults = { + 'state': lambda *a: 'init', + } + + def generate(self, cr, uid, ids, context=None): + """ + Main wizard step. Make sure that all modules are up-to-date, + then reinitialize all installed modules. + Equivalent of running the server with '-d <database> --init all' + + The goal of this is to fill the records table. + + TODO: update module list and versions, then update all modules? + """ + # Truncate the records table + if (openupgrade_tools.table_exists(cr, 'openupgrade_attribute') and + openupgrade_tools.table_exists(cr, 'openupgrade_record')): + cr.execute( + 'TRUNCATE openupgrade_attribute, openupgrade_record;' + ) + + # Need to get all modules in state 'installed' + module_obj = self.pool.get('ir.module.module') + module_ids = module_obj.search( + cr, uid, [('state', 'in', ['to install', 'to upgrade'])]) + if module_ids: + cr.commit() + _db, pool = pooler.restart_pool(cr.dbname, update_module=True) + # Did we succeed above? + module_ids = module_obj.search( + cr, uid, [('state', 'in', ['to install', 'to upgrade'])]) + if module_ids: + modules = module_obj.read( + cr, uid, module_ids, ['name'], context=context) + raise except_osv( + "Cannot reliably generate records", + ("Cannot seem to install or upgrade modules " + + ', '.join([x['name'] for x in modules]))) + # Now reinitialize all installed modules + module_ids = module_obj.search( + cr, uid, [('state', '=', 'installed')]) + module_obj.write( + cr, uid, module_ids, {'state': 'to install'}) + cr.commit() + _db, pool = pooler.restart_pool(cr.dbname, update_module=True) + self.write(cr, uid, ids, {'state': 'ready'}) + # and we are done + return True + +generate_records_wizard() + === added file 'openerp/addons/openupgrade_records/model/install_all_wizard.py' --- openerp/addons/openupgrade_records/model/install_all_wizard.py 1970-01-01 00:00:00 +0000 +++ openerp/addons/openupgrade_records/model/install_all_wizard.py 2014-04-08 14:03:57 +0000 @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module Copyright (C) 2012 OpenUpgrade community +# https://launchpad.net/~openupgrade-committers +# +# Contributors: +# Therp BV <http://therp.nl> +# +# 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/>. +# +############################################################################## + +import time +import os +from openerp.osv import osv, fields +from openerp import pooler + +class install_all_wizard(osv.osv_memory): + _name = 'openupgrade.install.all.wizard' + _description = 'OpenUpgrade Install All Wizard' + _columns = { + 'state': fields.selection([('init', 'init'), ('ready', 'ready')], 'State', readonly=True), + 'to_install': fields.integer('Number of modules to install', readonly=True), + } + _defaults = { + 'state': lambda *a: 'init', + } + + + def default_get(self, cr, uid, fields, context=None): + """ + Update module list and retrieve the number + of installable modules + """ + res = super(install_all_wizard, self).default_get( + cr, uid, fields, context=None) + module_obj = self.pool.get('ir.module.module') + update, add = module_obj.update_list(cr, uid,) + print "%s modules added" % add + module_ids = module_obj.search( + cr, uid, [('state', 'not in', ['installed', 'uninstallable', 'unknown'])]) + res.update( + {'to_install': module_ids and len(module_ids) or False} + ) + return res + + def quirk_fiscalyear(self, cr, uid, ids, context=None): + """ + Install account module first and create a fiscal year, + in order to prevent "No fiscal year defined" exception + during an upgrade or reinstallation of the account module. + + Refer to account_fiscalyear.find(), which is called as + a default function by the orm upon module upgrade. + """ + module_obj = self.pool.get('ir.module.module') + pool = self.pool + # Retrieve status of the account module + account_module_id = module_obj.search( + cr, uid, [('name', '=', 'account')], context=context)[0] + state = module_obj.read( + cr, uid, account_module_id, ['state'], context=context)['state'] + if state != 'installed': + # Cancel installation of other modules + module_ids = module_obj.search( + cr, uid, [('state', '=', 'to install')]) + module_obj.write(cr, uid, module_ids, {'state': 'uninstalled'}) + # Mark the module and its dependencies + module_obj.button_install(cr, uid, [account_module_id]) + # Install account module + cr.commit() + _db, pool = pooler.restart_pool(cr.dbname, update_module=True) + # get or create today's fiscal year + fy_obj = pool.get('account.fiscalyear') + if not fy_obj.find(cr, uid, False, exception=False, context=context): + fy_obj.create(cr, uid, { + 'name': time.strftime('%Y'), + 'code': time.strftime('%Y'), + 'date_start': "%s-01-01" % time.strftime('%Y'), + 'date_stop': "%s-12-31" % time.strftime('%Y'), + }) + + def install_all(self, cr, uid, ids, context=None): + """ + Main wizard step. Set all installable modules to install + and actually install them. + """ + module_obj = self.pool.get('ir.module.module') + module_ids = module_obj.search( + cr, uid, [('state', 'not in', ['installed', 'uninstallable', 'unknown'])]) + if module_ids: + module_obj.write( + cr, uid, module_ids, {'state': 'to install'}) + cr.commit() + _db, pool = pooler.restart_pool(cr.dbname, update_module=True) + self.write(cr, uid, ids, {'state': 'ready'}) + return True + +install_all_wizard() + === added file 'openerp/addons/openupgrade_records/model/openupgrade_record.py' --- openerp/addons/openupgrade_records/model/openupgrade_record.py 1970-01-01 00:00:00 +0000 +++ openerp/addons/openupgrade_records/model/openupgrade_record.py 2014-04-08 14:03:57 +0000 @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module Copyright (C) 2012 OpenUpgrade community +# https://launchpad.net/~openupgrade-committers +# +# Contributors: +# Therp BV <http://therp.nl> +# +# 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.osv import osv, fields + +# Cannot use forward references in 6.0 +class openupgrade_record(osv.osv): + _name = 'openupgrade.record' +openupgrade_record() + +class openupgrade_attribute(osv.osv): + _name = 'openupgrade.attribute' + _rec_name = 'name' + _columns = { + 'name': fields.char( + 'Name', size=24, + readonly=True, + ), + 'value': fields.char( + 'Value', + size=4096, + readonly=True, + ), + 'record_id': fields.many2one( + 'openupgrade.record', ondelete='CASCADE', + readonly=True, + ), + } +openupgrade_attribute() + +class openupgrade_record(osv.osv): + _inherit = 'openupgrade.record' + + _columns = { + 'name': fields.char('Name', size=256, readonly=True), + 'module': fields.char('Module', size=128, readonly=True), + 'model': fields.char('Model', size=128, readonly=True), + 'field': fields.char('Field', size=128, readonly=True), + 'mode': fields.selection( + [('create', 'Create'), ('modify', 'Modify')], + 'Mode', + help='Set to Create if a field is newly created ' + 'in this module. If this module modifies an attribute of an ' + 'exting field, set to Modify.', + readonly=True, + ), + 'type': fields.selection( + [('field', 'Field'), ('xmlid', 'XML ID')], + 'Type', + readonly=True, + ), + 'attribute_ids': fields.one2many( + 'openupgrade.attribute', 'record_id', 'Attributes', + readonly=True, + ), + } + def field_dump(self, cr, uid, context=None): + keys = [ + 'module', + 'mode', + 'model', + 'field', + 'type', + 'isfunction', + 'relation', + 'required', + 'selection_keys', + 'req_default', + 'inherits', + ] + + template = dict([(x, False) for x in keys]) + ids = self.search(cr, uid, [('type', '=', 'field')], context=context) + records = self.browse(cr, uid, ids, context=context) + data = [] + for record in records: + repr = template.copy() + repr.update({ + 'module': record.module, + 'model': record.model, + 'field': record.field, + 'mode': record.mode, + }) + repr.update( + dict([(x.name, x.value) for x in record.attribute_ids])) + data.append(repr) + return data + +openupgrade_record() === added directory 'openerp/addons/openupgrade_records/security' === added file 'openerp/addons/openupgrade_records/security/ir.model.access.csv' --- openerp/addons/openupgrade_records/security/ir.model.access.csv 1970-01-01 00:00:00 +0000 +++ openerp/addons/openupgrade_records/security/ir.model.access.csv 2014-04-08 14:03:57 +0000 @@ -0,0 +1,3 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +"access_openupgrade_record","openupgrade.record all","model_openupgrade_record",,1,0,0,0 +"access_openupgrade_attribute","openupgrade.attribute all","model_openupgrade_attribute",,1,0,0,0 === added directory 'openerp/addons/openupgrade_records/view' === added file 'openerp/addons/openupgrade_records/view/analysis_wizard.xml' --- openerp/addons/openupgrade_records/view/analysis_wizard.xml 1970-01-01 00:00:00 +0000 +++ openerp/addons/openupgrade_records/view/analysis_wizard.xml 2014-04-08 14:03:57 +0000 @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + <record id="view_openupgrade_analysis_wizard_form" model="ir.ui.view"> + <field name="name">view.openupgrade.analysis_wizard.form</field> + <field name="model">openupgrade.analysis.wizard</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="OpenUpgrade Analysis Wizard"> + <field name="server_config" readonly="1"/> + <field name="state"/> + <field name="log" colspan="4" + attrs="{'invisible': [('state', '!=', 'ready')]}"/> + <field name="write" + attrs="{'readonly': [('state', '!=', 'init')]}"/> + <button icon="gtk-close" + special="cancel" + string="Close" + /> + <button icon="gtk-ok" + string="Create" + name="get_communication" + type="object" + states="init" + /> + </form> + </field> + </record> + </data> +</openerp> === added file 'openerp/addons/openupgrade_records/view/comparison_config.xml' --- openerp/addons/openupgrade_records/view/comparison_config.xml 1970-01-01 00:00:00 +0000 +++ openerp/addons/openupgrade_records/view/comparison_config.xml 2014-04-08 14:03:57 +0000 @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + <record id="view_openupgrade_comparison_config_tree" model="ir.ui.view"> + <field name="name">view.openupgrade.comparison_config.tree</field> + <field name="model">openupgrade.comparison.config</field> + <field name="type">tree</field> + <field name="arch" type="xml"> + <tree string="OpenUpgrade Comparison Config"> + <field name="name" select="1"/> + <field name="protocol"/> + <field name="server" select="1"/> + <field name="port" select="1"/> + <field name="database" select="1"/> + </tree> + </field> + </record> + <record id="view_openupgrade_comparison_config_form" model="ir.ui.view"> + <field name="name">view.openupgrade.comparison_config.form</field> + <field name="model">openupgrade.comparison.config</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="OpenUpgrade Comparison Config"> + <field name="name"/> + <field name="protocol"/> + <field name="server"/> + <field name="port"/> + <field name="database"/> + <field name="username"/> + <field name="password" password="1"/> + <button + name="test_connection" + string="Test Connection" + type="object" icon="gtk-network" + colspan="2" + /> + <newline/> + <button + name="analyze" + string="Perform Analysis" + type="object" icon="gtk-execute" + colspan="2" + /> + <separator string="Last log" colspan="4"/> + <field name="last_log" nolabel="1" colspan="4"/> + </form> + </field> + </record> + <record id="action_openupgrade_comparison_config_tree" model="ir.actions.act_window"> + <field name="name">OpenUpgrade Comparison Configs</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">openupgrade.comparison.config</field> + <field name="view_type">form</field> + </record> + <menuitem + action="action_openupgrade_comparison_config_tree" + id="menu_openupgrade_comparison_config" + name="Comparison Configurations" + parent="menu_openupgrade" + /> + </data> +</openerp> === added file 'openerp/addons/openupgrade_records/view/generate_records_wizard.xml' --- openerp/addons/openupgrade_records/view/generate_records_wizard.xml 1970-01-01 00:00:00 +0000 +++ openerp/addons/openupgrade_records/view/generate_records_wizard.xml 2014-04-08 14:03:57 +0000 @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + <record id="view_openupgrade_generate_records_wizard_form" model="ir.ui.view"> + <field name="name">view.openupgrade.generate_records_wizard.form</field> + <field name="model">openupgrade.generate.records.wizard</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="OpenUpgrade Generate Records Wizard"> + <group states="init" colspan="4"> + <label string="This will reinitialize all the modules installed on this database. Do not continue if you use this database in production." + /> + <button icon="gtk-close" + special="cancel" + string="Cancel" + /> + <button icon="gtk-ok" + string="Continue" + name="generate" + type="object" + /> + </group> + <group states="ready" colspan="4"> + <label string="Modules initialized and records created" + /> + <field name="state" invisible="1"/> + <button icon="gtk-close" + special="cancel" + string="Close" + /> + </group> + </form> + </field> + </record> + + <record id="action_generate_records" model="ir.actions.act_window"> + <field name="name">Generate Records</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">openupgrade.generate.records.wizard</field> + <field name="view_type">form</field> + <field name="view_mode">form,tree</field> + <field name="target">new</field> + </record> + + <menuitem name="Generate Records" + id="menu_openupgrade_generate_records" + parent="menu_openupgrade" + action="action_generate_records" + sequence="15"/> + + </data> +</openerp> === added file 'openerp/addons/openupgrade_records/view/install_all_wizard.xml' --- openerp/addons/openupgrade_records/view/install_all_wizard.xml 1970-01-01 00:00:00 +0000 +++ openerp/addons/openupgrade_records/view/install_all_wizard.xml 2014-04-08 14:03:57 +0000 @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + <record id="view_openupgrade_install_all_wizard_form" model="ir.ui.view"> + <field name="name">view.openupgrade.install_all_wizard.form</field> + <field name="model">openupgrade.install.all.wizard</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="OpenUpgrade Install All Modules Wizard"> + <group states="init" colspan="4"> + <label string="This will install all modules on the database. Do not continue if you use this database in production." colspan="4" + /> + <field name="to_install"/> + <newline/> + <button icon="gtk-close" + special="cancel" + string="Cancel" + /> + <button icon="gtk-ok" + string="Continue" + name="install_all" + type="object" + /> + </group> + <group states="ready" colspan="4"> + <label string="Modules installed" + /> + <field name="state" invisible="1"/> + <button icon="gtk-close" + special="cancel" + string="Close" + /> + </group> + </form> + </field> + </record> + + <record id="action_install_all" model="ir.actions.act_window"> + <field name="name">Install All Modules</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">openupgrade.install.all.wizard</field> + <field name="view_type">form</field> + <field name="view_mode">form,tree</field> + <field name="target">new</field> + </record> + + <menuitem name="Install All Modules" + id="menu_openupgrade_install_all" + parent="menu_openupgrade" + action="action_install_all" + sequence="14"/> + + </data> +</openerp> === added file 'openerp/addons/openupgrade_records/view/openupgrade_record.xml' --- openerp/addons/openupgrade_records/view/openupgrade_record.xml 1970-01-01 00:00:00 +0000 +++ openerp/addons/openupgrade_records/view/openupgrade_record.xml 2014-04-08 14:03:57 +0000 @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + <!-- Top level menu under 'Database structure' --> + <menuitem + id="menu_openupgrade" + name="OpenUpgrade Development" + parent="base.menu_administration" + sequence="99" + /> + <record id="view_openupgrade_record_tree" model="ir.ui.view"> + <field name="name">view.openupgrade.record.tree</field> + <field name="model">openupgrade.record</field> + <field name="type">tree</field> + <field name="arch" type="xml"> + <tree string="OpenUpgrade Records"> + <field name="module" select="1"/> + <field name="model" select="1"/> + <field name="field" select="1"/> + <field name="name" select="1"/> + <field name="type" select="1"/> + <field name="mode" select="1"/> + </tree> + </field> + </record> + <record id="view_openupgrade_record_form" model="ir.ui.view"> + <field name="name">view.openupgrade.record.form</field> + <field name="model">openupgrade.record</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="OpenUpgrade Record"> + <field name="module" select="1"/> + <field name="model" select="1"/> + <field name="field" select="1"/> + <field name="name" select="1"/> + <field name="type" select="1"/> + <field name="mode" select="1"/> + <separator string="Attributes" colspan="4"/> + <field name="attribute_ids" mode="tree,form" nolabel="1" colspan="4"> + <tree string="Attributes"> + <field name="name"/> + <field name="value"/> + </tree> + <form string="Attribute"> + <field name="name"/> + <field name="value"/> + </form> + </field> + </form> + </field> + </record> + <record id="action_openupgrade_record_tree" model="ir.actions.act_window"> + <field name="name">OpenUpgrade Records</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">openupgrade.record</field> + <field name="view_type">form</field> + </record> + <menuitem + action="action_openupgrade_record_tree" + id="menu_openupgrade_records" + name="Records" + parent="menu_openupgrade" + /> + </data> +</openerp>
-- Mailing list: https://launchpad.net/~credativ Post to : [email protected] Unsubscribe : https://launchpad.net/~credativ More help : https://help.launchpad.net/ListHelp

