Ejemplo n.º 1
0
    def test_memory_cache_drop(self):
        "Test MemoryCache drop"
        cache.set('foo', 'bar')
        MemoryCache.drop(DB_NAME)

        self.assertEqual(cache.get('foo'), None)
Ejemplo n.º 2
0
 def tearDown(self):
     MemoryCache.drop(DB_NAME)
Ejemplo n.º 3
0
# This file is part of Tryton.  The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.

import time
import unittest

from trytond import backend, cache as cache_mod
from trytond.cache import freeze, MemoryCache
from trytond.tests.test_tryton import with_transaction, activate_module
from trytond.tests.test_tryton import DB_NAME, USER
from trytond.transaction import Transaction

cache = MemoryCache('test.cache')
cache_expire = MemoryCache('test.cache_expire', duration=1)


class CacheTestCase(unittest.TestCase):
    "Test Cache"

    def testFreeze(self):
        "Test freeze"
        self.assertEqual(freeze([1, 2, 3]), (1, 2, 3))
        self.assertEqual(freeze({
            'list': [1, 2, 3],
        }), frozenset([('list', (1, 2, 3))]))
        self.assertEqual(
            freeze({
                'dict': {
                    'inner dict': {
                        'list': [1, 2, 3],
                        'string': 'test',
Ejemplo n.º 4
0
class View(ModelSQL, ModelView):
    "View"
    __name__ = 'ir.ui.view'
    _rec_name = 'model'
    model = fields.Char('Model',
                        select=True,
                        states={
                            'required':
                            Eval('type').in_([None, 'tree', 'form', 'graph']),
                        })
    priority = fields.Integer('Priority', required=True, select=True)
    type = fields.Selection([
        (None, ''),
        ('tree', 'Tree'),
        ('form', 'Form'),
        ('graph', 'Graph'),
        ('calendar', 'Calendar'),
        ('board', 'Board'),
    ],
                            'View Type',
                            select=True,
                            domain=[
                                If(Bool(Eval('inherit')), ('type', '=', None),
                                   ('type', '!=', None)),
                            ],
                            depends=['inherit'])
    data = fields.Text('Data')
    name = fields.Char('Name',
                       states={
                           'invisible': ~(Eval('module') & Eval('name')),
                       },
                       depends=['module'],
                       readonly=True)
    arch = fields.Function(fields.Text('View Architecture',
                                       states={
                                           'readonly': Bool(Eval('name')),
                                       },
                                       depends=['name']),
                           'get_arch',
                           setter='set_arch')
    inherit = fields.Many2One('ir.ui.view',
                              'Inherited View',
                              select=True,
                              ondelete='CASCADE')
    field_childs = fields.Char('Children Field',
                               states={
                                   'invisible': Eval('type') != 'tree',
                               },
                               depends=['type'])
    module = fields.Char('Module',
                         states={
                             'invisible': ~Eval('module'),
                         },
                         readonly=True)
    domain = fields.Char('Domain',
                         states={
                             'invisible': ~Eval('inherit'),
                         },
                         depends=['inherit'])
    # AKE : Force usage of MemoryCache for non serializable data
    _get_rng_cache = MemoryCache('ir_ui_view.get_rng')

    @classmethod
    def __setup__(cls):
        super(View, cls).__setup__()
        cls._error_messages.update({
            'invalid_xml': 'Invalid XML for view "%s".',
        })
        cls._order.insert(0, ('priority', 'ASC'))
        cls._buttons.update({
            'show': {
                'readonly': Eval('type') != 'form',
            },
        })

    @classmethod
    def __register__(cls, module_name):
        TableHandler = backend.get('TableHandler')
        table = TableHandler(cls, module_name)

        # Migration from 2.4 arch moved into data
        if table.column_exist('arch'):
            table.column_rename('arch', 'data')

        super(View, cls).__register__(module_name)

        # New instance to refresh definition
        table = TableHandler(cls, module_name)

        # Migration from 1.0 arch no more required
        table.not_null_action('arch', action='remove')

        # Migration from 2.4 model no more required
        table.not_null_action('model', action='remove')

    @staticmethod
    def default_priority():
        return 16

    @staticmethod
    def default_module():
        return Transaction().context.get('module') or ''

    @classmethod
    @ModelView.button_action('ir.act_view_show')
    def show(cls, views):
        pass

    @classmethod
    def get_rng(cls, type_):
        key = (cls.__name__, type_)
        rng = cls._get_rng_cache.get(key, None)
        if rng is None:
            if sys.version_info < (3, ):
                filename = __file__.decode(sys.getfilesystemencoding())
            else:
                filename = __file__
            rng_name = os.path.join(os.path.dirname(filename), type_ + '.rng')
            with open(rng_name, 'rb') as fp:
                rng = etree.fromstring(fp.read())
            cls._get_rng_cache.set(key, rng)
        return rng

    @property
    def rng_type(self):
        if self.inherit:
            return self.inherit.rng_type
        return self.type

    @classmethod
    def validate(cls, views):
        super(View, cls).validate(views)
        cls.check_xml(views)

    @classmethod
    def check_xml(cls, views):
        "Check XML"
        for view in views:
            if not view.arch:
                continue
            xml = view.arch.strip()
            if not xml:
                continue
            try:
                tree = etree.fromstring(xml)
            except Exception:
                # JCA : print faulty xml
                try:
                    import pprint
                    pprint.pprint(xml)
                except:
                    print(xml)
                raise

            if hasattr(etree, 'RelaxNG'):
                validator = etree.RelaxNG(etree=cls.get_rng(view.rng_type))
                if not validator.validate(tree):
                    error_log = '\n'.join(
                        map(str, validator.error_log.filter_from_errors()))
                    logger.error('Invalid XML view %s:\n%s\n%s', view.rec_name,
                                 error_log, xml)
                    cls.raise_user_error('invalid_xml', (view.rec_name, ),
                                         error_log)
            root_element = tree.getroottree().getroot()

            # validate pyson attributes
            validates = {
                'states': fields.states_validate,
            }

            def encode(element):
                for attr in ('states', 'domain', 'spell', 'colors'):
                    if not element.get(attr):
                        continue
                    try:
                        value = PYSONDecoder().decode(element.get(attr))
                        validates.get(attr, lambda a: True)(value)
                    except Exception, e:
                        error_log = '%s: <%s %s="%s"/>' % (
                            e, element.get('id')
                            or element.get('name'), attr, element.get(attr))
                        logger.error('Invalid XML view %s:\n%s\n%s',
                                     view.rec_name, error_log, xml)
                        cls.raise_user_error('invalid_xml', (view.rec_name, ),
                                             error_log)
                for child in element:
                    encode(child)

            encode(root_element)
Ejemplo n.º 5
0
class ActionReport(ActionMixin, ModelSQL, ModelView):
    "Action report"
    __name__ = 'ir.action.report'
    _action_name = 'report_name'
    model = fields.Char('Model')
    report_name = fields.Char('Internal Name', required=True)
    report = fields.Char("Path",
                         states={
                             'invisible': Eval('is_custom', False),
                         },
                         depends=['is_custom'])
    report_content_custom = fields.Binary('Content')
    is_custom = fields.Function(fields.Boolean("Is Custom"), 'get_is_custom')
    report_content = fields.Function(fields.Binary(
        'Content', filename='report_content_name'),
                                     'get_report_content',
                                     setter='set_report_content')
    report_content_name = fields.Function(
        fields.Char('Content Name'), 'on_change_with_report_content_name')
    report_content_html = fields.Function(fields.Binary(
        "Content HTML",
        states={
            'invisible': ~Eval('template_extension').in_(['html', 'xhtml']),
        },
        depends=['template_extension']),
                                          'get_report_content_html',
                                          setter='set_report_content_html')
    action = fields.Many2One('ir.action',
                             'Action',
                             required=True,
                             ondelete='CASCADE')
    direct_print = fields.Boolean('Direct Print')
    single = fields.Boolean(
        "Single", help="Check if the template works only for one record.")
    translatable = fields.Boolean(
        "Translatable",
        help="Uncheck to disable translations for this report.")
    template_extension = fields.Selection([
        ('odt', 'OpenDocument Text'),
        ('odp', 'OpenDocument Presentation'),
        ('ods', 'OpenDocument Spreadsheet'),
        ('odg', 'OpenDocument Graphics'),
        ('txt', 'Plain Text'),
        ('xml', 'XML'),
        ('html', 'HTML'),
        ('xhtml', 'XHTML'),
    ],
                                          string='Template Extension',
                                          required=True,
                                          translate=False)
    extension = fields.Selection(
        [
            ('', ''),
            ('bib', 'BibTex'),
            ('bmp', 'Windows Bitmap'),
            ('csv', 'Text CSV'),
            ('dbf', 'dBase'),
            ('dif', 'Data Interchange Format'),
            ('doc', 'Microsoft Word 97/2000/XP'),
            ('doc6', 'Microsoft Word 6.0'),
            ('doc95', 'Microsoft Word 95'),
            ('docbook', 'DocBook'),
            ('docx', 'Microsoft Office Open XML Text'),
            ('docx7', 'Microsoft Word 2007 XML'),
            ('emf', 'Enhanced Metafile'),
            ('eps', 'Encapsulated PostScript'),
            ('gif', 'Graphics Interchange Format'),
            ('html', 'HTML Document'),
            ('jpg', 'Joint Photographic Experts Group'),
            ('met', 'OS/2 Metafile'),
            ('ooxml', 'Microsoft Office Open XML'),
            ('pbm', 'Portable Bitmap'),
            ('pct', 'Mac Pict'),
            ('pdb', 'AportisDoc (Palm)'),
            ('pdf', 'Portable Document Format'),
            ('pgm', 'Portable Graymap'),
            ('png', 'Portable Network Graphic'),
            ('ppm', 'Portable Pixelmap'),
            ('ppt', 'Microsoft PowerPoint 97/2000/XP'),
            ('psw', 'Pocket Word'),
            ('pwp', 'PlaceWare'),
            ('pxl', 'Pocket Excel'),
            ('ras', 'Sun Raster Image'),
            ('rtf', 'Rich Text Format'),
            ('latex', 'LaTeX 2e'),
            ('sda', 'StarDraw 5.0 (OpenOffice.org Impress)'),
            ('sdc', 'StarCalc 5.0'),
            ('sdc4', 'StarCalc 4.0'),
            ('sdc3', 'StarCalc 3.0'),
            ('sdd', 'StarImpress 5.0'),
            ('sdd3', 'StarDraw 3.0 (OpenOffice.org Impress)'),
            ('sdd4', 'StarImpress 4.0'),
            ('sdw', 'StarWriter 5.0'),
            ('sdw4', 'StarWriter 4.0'),
            ('sdw3', 'StarWriter 3.0'),
            ('slk', 'SYLK'),
            ('svg', 'Scalable Vector Graphics'),
            ('svm', 'StarView Metafile'),
            ('swf', 'Macromedia Flash (SWF)'),
            ('sxc', 'OpenOffice.org 1.0 Spreadsheet'),
            ('sxi', 'OpenOffice.org 1.0 Presentation'),
            ('sxd', 'OpenOffice.org 1.0 Drawing'),
            ('sxd3', 'StarDraw 3.0'),
            ('sxd5', 'StarDraw 5.0'),
            ('sxw', 'Open Office.org 1.0 Text Document'),
            ('text', 'Text Encoded'),
            ('tiff', 'Tagged Image File Format'),
            ('txt', 'Plain Text'),
            ('wmf', 'Windows Metafile'),
            ('xhtml', 'XHTML Document'),
            ('xls', 'Microsoft Excel 97/2000/XP'),
            ('xls5', 'Microsoft Excel 5.0'),
            ('xls95', 'Microsoft Excel 95'),
            ('xlsx', 'Microsoft Excel 2007/2010 XML'),
            ('xpm', 'X PixMap'),
        ],
        translate=False,
        string='Extension',
        help='Leave empty for the same as template, '
        'see LibreOffice documentation for compatible format.')
    module = fields.Char('Module', readonly=True, select=True)
    _template_cache = MemoryCache('ir.action.report.template', context=False)

    @classmethod
    def __register__(cls, module_name):
        super(ActionReport, cls).__register__(module_name)

        transaction = Transaction()
        cursor = transaction.connection.cursor()
        table = cls.__table_handler__(module_name)
        action_report = cls.__table__()

        # Migration from 3.4 remove report_name_module_uniq constraint
        table.drop_constraint('report_name_module_uniq')

        # Migration from 4.4 replace plain extension by txt
        cursor.execute(
            *action_report.update([action_report.extension], ['txt'],
                                  where=action_report.extension == 'plain'))

    @staticmethod
    def default_type():
        return 'ir.action.report'

    @staticmethod
    def default_report_content():
        return None

    @staticmethod
    def default_direct_print():
        return False

    @classmethod
    def default_single(cls):
        return False

    @classmethod
    def default_translatable(cls):
        return True

    @staticmethod
    def default_template_extension():
        return 'odt'

    @staticmethod
    def default_extension():
        return ''

    @staticmethod
    def default_module():
        return Transaction().context.get('module') or ''

    def get_is_custom(self, name):
        return bool(self.report_content_custom)

    @classmethod
    def get_report_content(cls, reports, name):
        contents = {}
        converter = fields.Binary.cast
        default = None
        format_ = Transaction().context.get('%s.%s' % (cls.__name__, name), '')
        if format_ == 'size':
            converter = len
            default = 0
        for report in reports:
            data = getattr(report, name + '_custom')
            if not data and getattr(report, name[:-8]):
                try:
                    with file_open(getattr(report,
                                           name[:-8]).replace('/', os.sep),
                                   mode='rb') as fp:
                        data = fp.read()
                except Exception:
                    data = None
            contents[report.id] = converter(data) if data else default
        return contents

    @classmethod
    def set_report_content(cls, records, name, value):
        cls.write(records, {'%s_custom' % name: value})

    @classmethod
    def get_report_content_html(cls, reports, name):
        return cls.get_report_content(reports, name[:-5])

    @classmethod
    def set_report_content_html(cls, reports, name, value):
        if value is not None:
            value = value.encode('utf-8')
        cls.set_report_content(reports, name[:-5], value)

    @fields.depends('name', 'template_extension')
    def on_change_with_report_content_name(self, name=None):
        return ''.join(
            filter(None, [self.name, os.extsep, self.template_extension]))

    @classmethod
    def get_pyson(cls, reports, name):
        pysons = {}
        field = name[6:]
        defaults = {}
        for report in reports:
            pysons[report.id] = (getattr(report, field)
                                 or defaults.get(field, 'null'))
        return pysons

    @classmethod
    def copy(cls, reports, default=None):
        if default is None:
            default = {}
        default = default.copy()
        default.setdefault('module', None)

        new_reports = []
        for report in reports:
            if report.report:
                default['report_content'] = None
                default['report'] = None
            default['report_name'] = report.report_name
            new_reports.extend(
                super(ActionReport, cls).copy([report], default=default))
        return new_reports

    @classmethod
    def write(cls, reports, values, *args):
        context = Transaction().context
        if 'module' in context:
            actions = iter((reports, values) + args)
            args = []
            for reports, values in zip(actions, actions):
                values = values.copy()
                values['module'] = context['module']
                args.extend((reports, values))
            reports, values = args[:2]
            args = args[2:]
        cls._template_cache.clear()
        super(ActionReport, cls).write(reports, values, *args)

    def get_template_cached(self):
        return self._template_cache.get(self.id)

    def set_template_cached(self, template):
        self._template_cache.set(self.id, template)
Ejemplo n.º 6
0
class View(ModelSQL, ModelView):
    "View"
    __name__ = 'ir.ui.view'
    _rec_name = 'model'
    model = fields.Char('Model',
                        select=True,
                        states={
                            'required':
                            Eval('type').in_([None, 'tree', 'form', 'graph']),
                        })
    priority = fields.Integer('Priority', required=True, select=True)
    type = fields.Selection([
        (None, ''),
        ('tree', 'Tree'),
        ('form', 'Form'),
        ('graph', 'Graph'),
        ('calendar', 'Calendar'),
        ('board', 'Board'),
    ],
                            'View Type',
                            select=True,
                            domain=[
                                If(Bool(Eval('inherit')), ('type', '=', None),
                                   ('type', '!=', None)),
                            ],
                            depends=['inherit'])
    data = fields.Text('Data')
    name = fields.Char('Name',
                       states={
                           'invisible': ~(Eval('module') & Eval('name')),
                       },
                       depends=['module'],
                       readonly=True)
    arch = fields.Function(fields.Text('View Architecture',
                                       states={
                                           'readonly': Bool(Eval('name')),
                                       },
                                       depends=['name']),
                           'get_arch',
                           setter='set_arch')
    inherit = fields.Many2One('ir.ui.view',
                              'Inherited View',
                              select=True,
                              ondelete='CASCADE')
    field_childs = fields.Char('Children Field',
                               states={
                                   'invisible': Eval('type') != 'tree',
                               },
                               depends=['type'])
    module = fields.Char('Module',
                         states={
                             'invisible': ~Eval('module'),
                         },
                         readonly=True)
    domain = fields.Char('Domain',
                         states={
                             'invisible': ~Eval('inherit'),
                         },
                         depends=['inherit'])
    # AKE : Force usage of MemoryCache for non serializable data
    _get_rng_cache = MemoryCache('ir_ui_view.get_rng')

    @classmethod
    def __setup__(cls):
        super(View, cls).__setup__()
        cls._error_messages.update({
            'invalid_xml': 'Invalid XML for view "%s".',
        })
        cls._order.insert(0, ('priority', 'ASC'))
        cls._buttons.update({
            'show': {
                'readonly': Eval('type') != 'form',
                'depends': ['type'],
            },
        })

    @staticmethod
    def default_priority():
        return 16

    @staticmethod
    def default_module():
        return Transaction().context.get('module') or ''

    @classmethod
    @ModelView.button_action('ir.act_view_show')
    def show(cls, views):
        pass

    @classmethod
    @memoize(10)
    def get_rng(cls, type_):
        key = (cls.__name__, type_)
        rng = cls._get_rng_cache.get(key)
        if rng is None:
            rng_name = os.path.join(os.path.dirname(__file__), type_ + '.rng')
            with open(rng_name, 'rb') as fp:
                rng = etree.fromstring(fp.read())
            cls._get_rng_cache.set(key, rng)
        return rng

    @property
    def rng_type(self):
        if self.inherit:
            return self.inherit.rng_type
        return self.type

    @classmethod
    def validate(cls, views):
        super(View, cls).validate(views)
        cls.check_xml(views)

    @classmethod
    def check_xml(cls, views):
        "Check XML"
        for view in views:
            if not view.arch:
                continue
            xml = view.arch.strip()
            if not xml:
                continue
            try:
                tree = etree.fromstring(xml)
            except Exception:
                # JCA : print faulty xml
                try:
                    import pprint
                    pprint.pprint(xml)
                except:
                    print(xml)
                raise

            if hasattr(etree, 'RelaxNG'):
                validator = etree.RelaxNG(etree=cls.get_rng(view.rng_type))
                if not validator.validate(tree):
                    error_log = '\n'.join(
                        map(str, validator.error_log.filter_from_errors()))
                    logger.error('Invalid XML view %s:\n%s\n%s', view.rec_name,
                                 error_log, xml)
                    cls.raise_user_error('invalid_xml', (view.rec_name, ),
                                         error_log)
            root_element = tree.getroottree().getroot()

            # validate pyson attributes
            validates = {
                'states': fields.states_validate,
            }

            def encode(element):
                for attr in ('states', 'domain', 'spell', 'colors'):
                    if not element.get(attr):
                        continue
                    try:
                        value = PYSONDecoder().decode(element.get(attr))
                        validates.get(attr, lambda a: True)(value)
                    except Exception as e:
                        error_log = '%s: <%s %s="%s"/>' % (
                            e, element.get('id')
                            or element.get('name'), attr, element.get(attr))
                        logger.error('Invalid XML view %s:\n%s\n%s',
                                     view.rec_name, error_log, xml)
                        cls.raise_user_error('invalid_xml', (view.rec_name, ),
                                             error_log)
                for child in element:
                    encode(child)

            encode(root_element)

    def get_arch(self, name):
        value = None
        if self.name and self.module:
            path = os.path.join(self.module, 'view', self.name + '.xml')
            try:
                with file_open(path,
                               subdir='modules',
                               mode='r',
                               encoding='utf-8') as fp:
                    value = fp.read()
            except IOError:
                pass
        if not value:
            value = self.data
        return value

    @classmethod
    def set_arch(cls, views, name, value):
        cls.write(views, {'data': value})

    @classmethod
    def delete(cls, views):
        super(View, cls).delete(views)
        # Restart the cache
        ModelView._fields_view_get_cache.clear()

    @classmethod
    def create(cls, vlist):
        views = super(View, cls).create(vlist)
        # Restart the cache
        ModelView._fields_view_get_cache.clear()
        return views

    @classmethod
    def write(cls, views, values, *args):
        super(View, cls).write(views, values, *args)
        # Restart the cache
        ModelView._fields_view_get_cache.clear()