<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
#    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 copy
from functools import partial
import itertools
import logging
import os
import sys
import time

from lxml import etree

from openerp import tools
from openerp.modules import module
from openerp.osv import fields, osv, orm
from openerp.tools import graph, SKIPPED_ELEMENT_TYPES
from openerp.tools.safe_eval import safe_eval as eval
from openerp.tools.translate import _
from openerp.tools.view_validation import valid_view
from openerp.tools import misc, qweb

_logger = logging.getLogger(__name__)

class view_custom(osv.osv):
    _name = 'ir.ui.view.custom'
    _order = 'create_date desc'  # search(limit=1) should return the last customization
    _columns = {
        'ref_id': fields.many2one('ir.ui.view', 'Original View', select=True, required=True, ondelete='cascade'),
        'user_id': fields.many2one('res.users', 'User', select=True, required=True, ondelete='cascade'),
        'arch': fields.text('View Architecture', required=True),
    }

    def _auto_init(self, cr, context=None):
        super(view_custom, self)._auto_init(cr, context)
        cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = \'ir_ui_view_custom_user_id_ref_id\'')
        if not cr.fetchone():
            cr.execute('CREATE INDEX ir_ui_view_custom_user_id_ref_id ON ir_ui_view_custom (user_id, ref_id)')

class view(osv.osv):
    _name = 'ir.ui.view'

    class NoViewError(Exception): pass
    class NoDefaultError(NoViewError): pass

    def _type_field(self, cr, uid, ids, name, args, context=None):
        result = {}
        for record in self.browse(cr, uid, ids, context):
            # Get the type from the inherited view if any.
            if record.inherit_id:
                result[record.id] = record.inherit_id.type
            else:
                result[record.id] = etree.fromstring(record.arch.encode('utf8')).tag
        return result

    def _arch_get(self, cr, uid, ids, name, arg, context=None):
        """
        For each id being read, return arch_db or the content of arch_file
        """
        result = {}
        for record in self.read(cr, uid, ids, ['arch_file', 'arch_db'], context=context):
            if record['arch_db']:
                result[record['id']] = record['arch_db']
                continue

            view_module, path = record['arch_file'].split('/', 1)
            arch_path = module.get_module_resource(view_module, path)
            if not arch_path:
                raise IOError("No file '%s' in module '%s'" % (path, view_module))

            with misc.file_open(arch_path) as f:
                result[record['id']] = f.read().decode('utf-8')

        return result

    def _arch_set(self, cr, uid, id, name, value, arg, context=None):
        """
        Forward writing to arch_db
        """
        self.write(cr, uid, id, {'arch_db': value}, context=context)

    _columns = {
        'name': fields.char('View Name', required=True),
        'model': fields.char('Object', size=64, select=True),
        'priority': fields.integer('Sequence', required=True),
        'type': fields.selection([
            ('tree','Tree'),
            ('form','Form'),
            ('mdx','mdx'),
            ('graph', 'Graph'),
            ('calendar', 'Calendar'),
            ('diagram','Diagram'),
            ('gantt', 'Gantt'),
            ('kanban', 'Kanban'),
            ('search','Search'),
            ('qweb', 'QWeb')], string='View Type'),
        'arch_file': fields.char("View path"),
        'arch_db': fields.text("Arch content", oldname='arch'),
        'arch': fields.function(_arch_get, fnct_inv=_arch_set, store=False, string="View Architecture", type='text', nodrop=True),
        'inherit_id': fields.many2one('ir.ui.view', 'Inherited View', ondelete='cascade', select=True),
        'field_parent': fields.char('Child Field',size=64),
        'xml_id': fields.function(osv.osv.get_xml_id, type='char', size=128, string="External ID",
                                  help="ID of the view defined in xml file"),
        'groups_id': fields.many2many('res.groups', 'ir_ui_view_group_rel', 'view_id', 'group_id',
            string='Groups', help="If this field is empty, the view applies to all users. Otherwise, the view applies to the users of those groups only."),
        'model_ids': fields.one2many('ir.model.data', 'res_id', auto_join=True),
    }
    _defaults = {
        'priority': 16,
    }
    _order = "priority,name"

    # Holds the RNG schema
    _relaxng_validator = None

    def create(self, cr, uid, values, context=None):
        if not 'type' in values:
            if values.get('inherit_id'):
                values['type'] = self.browse(cr, uid, values['inherit_id'], context).type
            else:
                values['type'] = etree.fromstring(values['arch'].encode('utf8')).tag
        if not values.get('name'):
            values['name'] = "%s %s" % (values['model'], values['type'])
        return super(view, self).create(cr, uid, values, context)

    def _relaxng(self):
        if not self._relaxng_validator:
            frng = tools.file_open(os.path.join('base','rng','view.rng'))
            try:
                relaxng_doc = etree.parse(frng)
                self._relaxng_validator = etree.RelaxNG(relaxng_doc)
            except Exception:
                _logger.exception('Failed to load RelaxNG XML schema for views validation')
            finally:
                frng.close()
        return self._relaxng_validator

    def _check_xml(self, cr, uid, ids, context=None):
        for view in self.browse(cr, uid, ids, context):
            # Sanity check: the view should not break anything upon rendering!
            try:
                fvg = self.read_combined(cr, uid, view.id, view.type, view.model, context=context)
                view_arch_utf8 = fvg['arch']
            except Exception, e:<commit_msg>[FIX] views: correct type detection<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
#    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 copy
from functools import partial
import itertools
import logging
import os
import sys
import time

from lxml import etree

from openerp import tools
from openerp.modules import module
from openerp.osv import fields, osv, orm
from openerp.tools import graph, SKIPPED_ELEMENT_TYPES
from openerp.tools.safe_eval import safe_eval as eval
from openerp.tools.translate import _
from openerp.tools.view_validation import valid_view
from openerp.tools import misc, qweb

_logger = logging.getLogger(__name__)

class view_custom(osv.osv):
    _name = 'ir.ui.view.custom'
    _order = 'create_date desc'  # search(limit=1) should return the last customization
    _columns = {
        'ref_id': fields.many2one('ir.ui.view', 'Original View', select=True, required=True, ondelete='cascade'),
        'user_id': fields.many2one('res.users', 'User', select=True, required=True, ondelete='cascade'),
        'arch': fields.text('View Architecture', required=True),
    }

    def _auto_init(self, cr, context=None):
        super(view_custom, self)._auto_init(cr, context)
        cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = \'ir_ui_view_custom_user_id_ref_id\'')
        if not cr.fetchone():
            cr.execute('CREATE INDEX ir_ui_view_custom_user_id_ref_id ON ir_ui_view_custom (user_id, ref_id)')

class view(osv.osv):
    _name = 'ir.ui.view'

    class NoViewError(Exception): pass
    class NoDefaultError(NoViewError): pass

    def _type_field(self, cr, uid, ids, name, args, context=None):
        result = {}
        for record in self.browse(cr, uid, ids, context):
            # Get the type from the inherited view if any.
            if record.inherit_id:
                result[record.id] = record.inherit_id.type
            else:
                result[record.id] = etree.fromstring(record.arch.encode('utf8')).tag
        return result

    def _arch_get(self, cr, uid, ids, name, arg, context=None):
        """
        For each id being read, return arch_db or the content of arch_file
        """
        result = {}
        for record in self.read(cr, uid, ids, ['arch_file', 'arch_db'], context=context):
            if record['arch_db']:
                result[record['id']] = record['arch_db']
                continue

            view_module, path = record['arch_file'].split('/', 1)
            arch_path = module.get_module_resource(view_module, path)
            if not arch_path:
                raise IOError("No file '%s' in module '%s'" % (path, view_module))

            with misc.file_open(arch_path) as f:
                result[record['id']] = f.read().decode('utf-8')

        return result

    def _arch_set(self, cr, uid, id, name, value, arg, context=None):
        """
        Forward writing to arch_db
        """
        self.write(cr, uid, id, {'arch_db': value}, context=context)

    _columns = {
        'name': fields.char('View Name', required=True),
        'model': fields.char('Object', size=64, select=True),
        'priority': fields.integer('Sequence', required=True),
        'type': fields.selection([
            ('tree','Tree'),
            ('form','Form'),
            ('mdx','mdx'),
            ('graph', 'Graph'),
            ('calendar', 'Calendar'),
            ('diagram','Diagram'),
            ('gantt', 'Gantt'),
            ('kanban', 'Kanban'),
            ('search','Search'),
            ('qweb', 'QWeb')], string='View Type'),
        'arch_file': fields.char("View path"),
        'arch_db': fields.text("Arch content", oldname='arch'),
        'arch': fields.function(_arch_get, fnct_inv=_arch_set, store=False, string="View Architecture", type='text', nodrop=True),
        'inherit_id': fields.many2one('ir.ui.view', 'Inherited View', ondelete='cascade', select=True),
        'field_parent': fields.char('Child Field',size=64),
        'xml_id': fields.function(osv.osv.get_xml_id, type='char', size=128, string="External ID",
                                  help="ID of the view defined in xml file"),
        'groups_id': fields.many2many('res.groups', 'ir_ui_view_group_rel', 'view_id', 'group_id',
            string='Groups', help="If this field is empty, the view applies to all users. Otherwise, the view applies to the users of those groups only."),
        'model_ids': fields.one2many('ir.model.data', 'res_id', auto_join=True),
    }
    _defaults = {
        'priority': 16,
    }
    _order = "priority,name"

    # Holds the RNG schema
    _relaxng_validator = None

    def create(self, cr, uid, values, context=None):
        if 'type' not in values:
            if values.get('inherit_id'):
                values['type'] = self.browse(cr, uid, values['inherit_id'], context).type
            else:
                values['type'] = etree.fromstring(values['arch']).tag

        if not values.get('name'):
            values['name'] = "%s %s" % (values['model'], values['type'])
        return super(view, self).create(cr, uid, values, context)

    def _relaxng(self):
        if not self._relaxng_validator:
            frng = tools.file_open(os.path.join('base','rng','view.rng'))
            try:
                relaxng_doc = etree.parse(frng)
                self._relaxng_validator = etree.RelaxNG(relaxng_doc)
            except Exception:
                _logger.exception('Failed to load RelaxNG XML schema for views validation')
            finally:
                frng.close()
        return self._relaxng_validator

    def _check_xml(self, cr, uid, ids, context=None):
        for view in self.browse(cr, uid, ids, context):
            # Sanity check: the view should not break anything upon rendering!
            try:
                fvg = self.read_combined(cr, uid, view.id, view.type, view.model, context=context)
                view_arch_utf8 = fvg['arch']
            except Exception, e:
{'fraction_non_alphanumeric': 0.14571178529754958, 'fraction_numerical': 0.004302800466744457, 'mean_word_length': 2.782896551724138, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 10}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7041737', 'n_tokens_mistral': 4085, 'n_tokens_neox': 3941, 'n_words': 1133}