<commit_before># Copyright (c) 2013 Rackspace, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import sys

import six
import testtools
import httpretty
import uuid
import json

from barbicanclient.test import keystone_client_fixtures
from barbicanclient.test import test_client
import barbicanclient.barbican

class WhenTestingBarbicanCLI(test_client.BaseEntityResource):

    def setUp(self):
        self._setUp('barbican')

    def barbican(self, argstr):
        """Source: Keystone client's shell method in test_shell.py"""
        orig = sys.stdout
        orig_err = sys.stderr
        clean_env = {}
        _old_env, os.environ = os.environ, clean_env.copy()
        exit_code = 0
        try:
            sys.stdout = six.StringIO()
            sys.stderr = sys.stdout
            _barbican = barbicanclient.barbican.Barbican()
            _barbican.execute(argv=argstr.split())
        except SystemExit:
            exc_type, exc_value, exc_traceback = sys.exc_info()
            exit_code = exc_value.code
        finally:
            if exit_code == 0:
                out = sys.stdout.getvalue()
            else:
                out = sys.stderr.getvalue()
            sys.stdout.close()
            sys.stdout = orig
            sys.stderr = orig_err
            os.environ = _old_env
        return exit_code, out

    def test_should_show_usage_error_with_no_args(self):
        args = ""
        exit_code, out = self.barbican(args)
        self.assertEqual(2, exit_code)
        self.assertIn('error: the following', out)

    def test_should_show_usage_with_help_flag(self):
        args = "-h"
        exit_code, out = self.barbican(args)
        self.assertEqual(0, exit_code)
        self.assertIn('usage: ', out)

    def test_should_error_if_noauth_and_authurl_both_specified(self):
        args = "--no-auth --os-auth-url http://localhost:5000/v3"
        exit_code, out = self.barbican(args)
        self.assertEqual(2, exit_code)
        self.assertIn(
            'error: argument --os-auth-url/-A: not allowed with '
            'argument --no-auth/-N', out)

    def _expect_error_with_invalid_noauth_args(self, args):
        exit_code, out = self.barbican(args)
        self.assertEqual(1, exit_code)
        expected_err_msg = 'ERROR: please specify --endpoint '\
                           'and --os-project-id(or --os-tenant-id)\n'
        self.assertIn(expected_err_msg, out)

    def test_should_error_if_noauth_and_missing_endpoint_tenantid_args(self):
        self._expect_error_with_invalid_noauth_args("--no-auth secret list")
        self._expect_error_with_invalid_noauth_args(
            "--no-auth --endpoint http://xyz secret list")
        self._expect_error_with_invalid_noauth_args(
            "--no-auth --os-tenant-id 123 secret list")
        self._expect_error_with_invalid_noauth_args(
            "--no-auth --os-project-id 123 secret list")

    def _expect_success_code(self, args):
        exit_code, out = self.barbican(args)
        self.assertEqual(0, exit_code)

    def _expect_failure_code(self, args, code=1):
        exit_code, out = self.barbican(args)
        self.assertEqual(code, exit_code)

    def _assert_status_code_and_msg(self, args, expected_msg, code=1):
        exit_code, out = self.barbican(args)
        self.assertEqual(code, exit_code)
        self.assertIn(expected_msg, out)

    @httpretty.activate
    def test_should_succeed_if_noauth_with_valid_args_specified(self):
        list_secrets_content = '{"secrets": [], "total": 0}'
        list_secrets_url = '%s%s/secrets' % (
            self.endpoint, self.tenant_id)
        httpretty.register_uri(
            httpretty.GET, list_secrets_url,
            body=list_secrets_content)
        self._expect_success_code(
            "--no-auth --endpoint %s --os-tenant-id %s secret list"
            % (self.endpoint, self.tenant_id))

    def test_should_error_if_required_keystone_auth_arguments_are_missing(
            self):
        expected_error_msg = 'ERROR: please specify authentication credentials'
        self._assert_status_code_and_msg(
            '--os-auth-url http://localhost:35357/v2.0 secret list',
            expected_error_msg)
        self._assert_status_code_and_msg('--os-auth-url '
                                         'http://localhost:35357/v2.0 '
                                         '--os-username barbican '
                                         '--os-password barbican '
                                         'secret list', expected_error_msg)

class TestBarbicanWithKeystoneClient(testtools.TestCase):

    def setUp(self):
        super(TestBarbicanWithKeystoneClient, self).setUp()
        self.kwargs = {'auth_url': keystone_client_fixtures.V3_URL}
        for arg in ['username', 'password', 'project_name',
                    'user_domain_name', 'project_domain_name']:
            self.kwargs[arg] = uuid.uuid4().hex
        self.barbican = barbicanclient.barbican.Barbican()

    def _to_argv(self, **kwargs):
        """Format Keystone client arguments into command line argv."""
        argv = []
        for k, v in six.iteritems(kwargs):
            argv.append('--os-' + k.replace('_', '-'))
            argv.append(v)
        return argv

    @httpretty.activate
    def test_v2_auth(self):
        self.kwargs['auth_url'] = keystone_client_fixtures.V2_URL
        argv = self._to_argv(**self.kwargs)
        argv.append('secret')
        argv.append('list')
        argv.append('-h')
        argv.append('mysecretid')
        # emulate Keystone version discovery
        httpretty.register_uri(httpretty.GET,
                               self.kwargs['auth_url'],
                               body=keystone_client_fixtures.V2_VERSION_ENTRY)
        # emulate Keystone v2 token request
        v2_token = keystone_client_fixtures.generate_v2_project_scoped_token()
        httpretty.register_uri(httpretty.POST,
                               '%s/tokens' % (self.kwargs['auth_url']),
                               body=json.dumps(v2_token))
        # emulate get secrets
        barbican_url = keystone_client_fixtures.BARBICAN_ENDPOINT
        httpretty.register_uri(
            httpretty.DELETE,
            '%s/%s/secrets/mysecretid' % (
                barbican_url,
                v2_token['access']['token']['tenant']['id']),
            status=200)
        self.barbican.execute(argv=argv)

    @httpretty.activate
    def test_v3_auth(self):
        argv = self._to_argv(**self.kwargs)
        argv.append('secret')
        argv.append('list')
        argv.append('-h')
        argv.append('mysecretid')
        # emulate Keystone version discovery
        httpretty.register_uri(httpretty.GET,
                               self.kwargs['auth_url'],
                               body=keystone_client_fixtures.V3_VERSION_ENTRY)
        # emulate Keystone v3 token request
        id, v3_token = \
            keystone_client_fixtures.generate_v3_project_scoped_token()
        httpretty.register_uri(httpretty.POST,
                               '%s/auth/tokens' % (self.kwargs['auth_url']),
                               body=json.dumps(v3_token))
        # emulate delete secret
        barbican_url = keystone_client_fixtures.BARBICAN_ENDPOINT
        httpretty.register_uri(
            httpretty.DELETE,
            '%s/%s/secrets/mysecretid' % (
                barbican_url,
                v3_token['token']['project']['id']),
            status=200)
        self.barbican.execute(argv=argv)
<commit_msg>Fix Testing Failure due to Argparse<commit_after># Copyright (c) 2013 Rackspace, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import sys

import six
import testtools
import httpretty
import uuid
import json

from barbicanclient.test import keystone_client_fixtures
from barbicanclient.test import test_client
import barbicanclient.barbican

class WhenTestingBarbicanCLI(test_client.BaseEntityResource):

    def setUp(self):
        self._setUp('barbican')

    def barbican(self, argstr):
        """Source: Keystone client's shell method in test_shell.py"""
        orig = sys.stdout
        orig_err = sys.stderr
        clean_env = {}
        _old_env, os.environ = os.environ, clean_env.copy()
        exit_code = 0
        try:
            sys.stdout = six.StringIO()
            sys.stderr = sys.stdout
            _barbican = barbicanclient.barbican.Barbican()
            _barbican.execute(argv=argstr.split())
        except SystemExit:
            exc_type, exc_value, exc_traceback = sys.exc_info()
            exit_code = exc_value.code
        finally:
            if exit_code == 0:
                out = sys.stdout.getvalue()
            else:
                out = sys.stderr.getvalue()
            sys.stdout.close()
            sys.stdout = orig
            sys.stderr = orig_err
            os.environ = _old_env
        return exit_code, out

    def test_should_show_usage_error_with_no_args(self):
        args = ""
        exit_code, out = self.barbican(args)
        self.assertEqual(2, exit_code)
        self.assertIn('usage:', out)

    def test_should_show_usage_with_help_flag(self):
        args = "-h"
        exit_code, out = self.barbican(args)
        self.assertEqual(0, exit_code)
        self.assertIn('usage: ', out)

    def test_should_error_if_noauth_and_authurl_both_specified(self):
        args = "--no-auth --os-auth-url http://localhost:5000/v3"
        exit_code, out = self.barbican(args)
        self.assertEqual(2, exit_code)
        self.assertIn(
            'error: argument --os-auth-url/-A: not allowed with '
            'argument --no-auth/-N', out)

    def _expect_error_with_invalid_noauth_args(self, args):
        exit_code, out = self.barbican(args)
        self.assertEqual(1, exit_code)
        expected_err_msg = 'ERROR: please specify --endpoint '\
                           'and --os-project-id(or --os-tenant-id)\n'
        self.assertIn(expected_err_msg, out)

    def test_should_error_if_noauth_and_missing_endpoint_tenantid_args(self):
        self._expect_error_with_invalid_noauth_args("--no-auth secret list")
        self._expect_error_with_invalid_noauth_args(
            "--no-auth --endpoint http://xyz secret list")
        self._expect_error_with_invalid_noauth_args(
            "--no-auth --os-tenant-id 123 secret list")
        self._expect_error_with_invalid_noauth_args(
            "--no-auth --os-project-id 123 secret list")

    def _expect_success_code(self, args):
        exit_code, out = self.barbican(args)
        self.assertEqual(0, exit_code)

    def _expect_failure_code(self, args, code=1):
        exit_code, out = self.barbican(args)
        self.assertEqual(code, exit_code)

    def _assert_status_code_and_msg(self, args, expected_msg, code=1):
        exit_code, out = self.barbican(args)
        self.assertEqual(code, exit_code)
        self.assertIn(expected_msg, out)

    @httpretty.activate
    def test_should_succeed_if_noauth_with_valid_args_specified(self):
        list_secrets_content = '{"secrets": [], "total": 0}'
        list_secrets_url = '%s%s/secrets' % (
            self.endpoint, self.tenant_id)
        httpretty.register_uri(
            httpretty.GET, list_secrets_url,
            body=list_secrets_content)
        self._expect_success_code(
            "--no-auth --endpoint %s --os-tenant-id %s secret list"
            % (self.endpoint, self.tenant_id))

    def test_should_error_if_required_keystone_auth_arguments_are_missing(
            self):
        expected_error_msg = 'ERROR: please specify authentication credentials'
        self._assert_status_code_and_msg(
            '--os-auth-url http://localhost:35357/v2.0 secret list',
            expected_error_msg)
        self._assert_status_code_and_msg('--os-auth-url '
                                         'http://localhost:35357/v2.0 '
                                         '--os-username barbican '
                                         '--os-password barbican '
                                         'secret list', expected_error_msg)

class TestBarbicanWithKeystoneClient(testtools.TestCase):

    def setUp(self):
        super(TestBarbicanWithKeystoneClient, self).setUp()
        self.kwargs = {'auth_url': keystone_client_fixtures.V3_URL}
        for arg in ['username', 'password', 'project_name',
                    'user_domain_name', 'project_domain_name']:
            self.kwargs[arg] = uuid.uuid4().hex
        self.barbican = barbicanclient.barbican.Barbican()

    def _to_argv(self, **kwargs):
        """Format Keystone client arguments into command line argv."""
        argv = []
        for k, v in six.iteritems(kwargs):
            argv.append('--os-' + k.replace('_', '-'))
            argv.append(v)
        return argv

    @httpretty.activate
    def test_v2_auth(self):
        self.kwargs['auth_url'] = keystone_client_fixtures.V2_URL
        argv = self._to_argv(**self.kwargs)
        argv.append('secret')
        argv.append('list')
        argv.append('-h')
        argv.append('mysecretid')
        # emulate Keystone version discovery
        httpretty.register_uri(httpretty.GET,
                               self.kwargs['auth_url'],
                               body=keystone_client_fixtures.V2_VERSION_ENTRY)
        # emulate Keystone v2 token request
        v2_token = keystone_client_fixtures.generate_v2_project_scoped_token()
        httpretty.register_uri(httpretty.POST,
                               '%s/tokens' % (self.kwargs['auth_url']),
                               body=json.dumps(v2_token))
        # emulate get secrets
        barbican_url = keystone_client_fixtures.BARBICAN_ENDPOINT
        httpretty.register_uri(
            httpretty.DELETE,
            '%s/%s/secrets/mysecretid' % (
                barbican_url,
                v2_token['access']['token']['tenant']['id']),
            status=200)
        self.barbican.execute(argv=argv)

    @httpretty.activate
    def test_v3_auth(self):
        argv = self._to_argv(**self.kwargs)
        argv.append('secret')
        argv.append('list')
        argv.append('-h')
        argv.append('mysecretid')
        # emulate Keystone version discovery
        httpretty.register_uri(httpretty.GET,
                               self.kwargs['auth_url'],
                               body=keystone_client_fixtures.V3_VERSION_ENTRY)
        # emulate Keystone v3 token request
        id, v3_token = \
            keystone_client_fixtures.generate_v3_project_scoped_token()
        httpretty.register_uri(httpretty.POST,
                               '%s/auth/tokens' % (self.kwargs['auth_url']),
                               body=json.dumps(v3_token))
        # emulate delete secret
        barbican_url = keystone_client_fixtures.BARBICAN_ENDPOINT
        httpretty.register_uri(
            httpretty.DELETE,
            '%s/%s/secrets/mysecretid' % (
                barbican_url,
                v3_token['token']['project']['id']),
            status=200)
        self.barbican.execute(argv=argv)
<|endoftext|>


<commit_before># -*- encoding: utf-8 -*-
##############################################################################
#
#    Author Guewen Baconnier. Copyright Camptocamp SA
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU 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 General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import time
import pooler
import logging
from osv import osv, fields
from tools.translate import _
from tools.safe_eval import safe_eval
from tools import DEFAULT_SERVER_DATETIME_FORMAT
import simplejson
from base_external_referentials.external_osv import ExternalSession

class external_report(osv.osv):
    _name = 'external.report'
    _description = 'External Report'
    _order = 'end_date desc'

    _columns = {
        'name': fields.char('Action', size=32, required=True,
                            readonly=True),
        'object_name': fields.char('Ressource Name', size=64, required=True,
                            readonly=True),
        'object_related': fields.char('Report Related To', size=64, required=True,
                            readonly=True),
        'object_related_description': fields.char('Report Related To', size=64, required=True,
                            readonly=True),
        'res_id': fields.integer('Ressource id', required=True, readonly=True),
        'method': fields.char('Method', size=64, required=True,
                           readonly=True,
                           help="Method linked to the report"),
        'start_date': fields.datetime('Last Start Date', readonly=True),
        'end_date': fields.datetime('Last End Date', readonly=True),
        'referential_id': fields.many2one('external.referential',
                                                   'External Referential',
                                                   required=True,
                                                   readonly=True),
        'line_ids': fields.one2many('external.report.line',
                                    'report_id', 'Report Lines'),
        'failed_line_ids': fields.one2many('external.report.line',
                                           'report_id',
                                           'Failed Report Lines',
                                           domain=[('state', '!=', 'success')]),
        'history_ids': fields.one2many('external.report.history',
                                       'report_id', 'History'),
    }

    def get_report_filter(self, cr, uid, method, object, context=None):
        return [
            ('method', '=', method),
            ('res_id', '=', object.id),
            ('object_related', '=', object._name),
        ]

    def get_report(self, cr, uid, method, object, context=None):
        report_id = False
        filter = self.get_report_filter(cr, uid, method, object, context=context)
        report = self.search(cr, uid, filter, context=context)
        if report:
            report_id = report[0]
        return report_id

    def _clean_successful_lines(self, cr, uid, report_id, context=None):
        lines_obj = self.pool.get('external.report.line')
        line_ids = lines_obj.search(cr, uid,
                                    [('report_id', '=', report_id),
                                    ('state', '=', 'success')],
                                    context=context)
        lines_obj.unlink(cr, uid, line_ids, context=context)
        return True

    def retry_failed_lines(self, cr, uid, ids, context=None):
        logging.getLogger('external_synchro').info("retry the failed lines of the reports ids %s" % (ids,))
        if isinstance(ids, int):
            ids = [ids]
        if not context:
            context={}
        context['origin'] = 'retry'
        for report in self.read(cr, uid, ids, ['failed_line_ids'], context=context):
            failed_line_ids = report['failed_line_ids']
            if failed_line_ids:
                context['report_id'] = report['id']
                self.pool.get('external.report.line').retry(cr, uid, failed_line_ids, context=context)
        return True

    def _prepare_start_report(self, cr, uid, method, object, context=None):
        return {'name': method.replace('_', ' ').strip(),
                'object_name': getattr(object, object._rec_name),
                'object_related': object._name,
                'object_related_description': object._description,
                'res_id': object.id,
                'method': method,
                'referential_id': object.referential_id.id,
                'start_date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),}

    def start_report(self, cr, uid, id=None, method=None,
                     object=None, context=None):
        """ Start a report, use the report with the id in the parameter
        if given. Otherwise, try to find the report which have the same method
         and object (we use the same report to avoid a
         multiplication of reports) If nothing is found, it create a new report
        """

        if not id and (not method or not object):
            raise Exception('No reference to create the report!')
        if id:
            report_id = id
        else:
            report_id = self.get_report(cr, uid, method, object, context)

        log_cr = pooler.get_db(cr.dbname).cursor()
        try:
            if report_id:
                self.write(log_cr, uid, report_id,
                           {'start_date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
                            'end_date': False},
                           context=context)
                # clean successful lines of the last report
                self._clean_successful_lines(log_cr, uid, report_id, context)
            else:
                report_id = self.create(
                    log_cr, uid,
                    self._prepare_start_report(
                        cr, uid, method, object, context=context),
                    context=context)
            log_cr.commit()

        finally:
            log_cr.close()

        return report_id

    def end_report(self, cr, uid, id, context=None):
        """ Create history lines based on lines
        Successful lines are cleaned at each start of a report
        so we historize their aggregation.
        """
        log_cr = pooler.get_db(cr.dbname).cursor()
        report = self.browse(log_cr, uid, id, context=context)
        lines_obj = self.pool.get('external.report.line')
        history_obj = self.pool.get('external.report.history')
        try:
            line_ids = lines_obj.search(log_cr, uid,
                                     [('report_id', '=', id),
                                     '|', ('write_date', '>', report.start_date),
                                     ('create_date', '>', report.start_date)],
                                     context=context)

            grouped_lines = lines_obj.aggregate_actions(log_cr, uid,
                                                        line_ids,
                                                        context)

            for line in grouped_lines:
                history_obj.create(log_cr, uid,
                                   {
                        'report_id': id,
                        'res_model': line[1],
                        'action': line[2],
                        'count': grouped_lines[line],
                        'user_id': uid,
                        'state': line[0],
                        'origin': context.get('origin', False),
                    }, context=context)

            self.write(log_cr, uid, id,
                       {'end_date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)},
                       context=context)

            log_cr.commit()
        finally:
            log_cr.close()
        return id

external_report()

class external_report_history(osv.osv):
    _name = 'external.report.history'
    _description = 'External Report History'
    _rec_name = 'report_id'
    _order = 'date desc'

    _columns = {
        'report_id': fields.many2one('external.report',
                                              'External Report',
                                              required=True,
                                              readonly=True,
                                              ondelete='cascade'),
        'date': fields.datetime('End Date', required=True, readonly=True),
        'res_model': fields.char('Resource Object', size=64,
                                 required=True, readonly=True),
        'action': fields.char('Action', size=64, required=True, readonly=True),
        'count': fields.integer('Count', readonly=True),
        'user_id': fields.many2one('res.users', 'User', required=True, readonly=True),
        'state': fields.selection((('success', 'Success'),
                                   ('fail', 'Failed')),
                                   'Status', required=True, readonly=True),
        'origin': fields.char('Origin', size=64, readonly=True),
    }

    _defaults = {
        "date": lambda *a: time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
    }

external_report_history()

class external_report_lines(osv.osv):
    _name = 'external.report.line'
    _description = 'External Report Lines'
    _rec_name = 'res_id'
    _order = 'date desc'

    def _get_resource(self, cr, uid, ids, field_name, arg, context=None):
        res = {}
        for report_line in self.browse(cr, uid, ids, context=context):
            res[report_line.id] = simplejson.dumps(report_line.resource)
        return res

    def _set_resource(self, cr, uid, ids, field_name, arg, context=None):
        res = {}
        for report_line in self.browse(cr, uid, ids, context=context):
            res[report_line.id] = simplejson.loads(report_line.resource)
        return res

    _columns = {
        'report_id': fields.many2one('external.report',
                                              'External Report',
                                              required=True,
                                              readonly=True,
                                              ondelete='restrict'),
        'state': fields.selection((('success', 'Success'),
                                   ('fail', 'Failed')),
                                   'Status', required=True, readonly=True),
        'res_model': fields.char('Resource Object', size=64,
                                 required=True, readonly=True),
        'res_id': fields.integer('Resource Id', readonly=True),
        'action': fields.char('Action', size=32, required=True, readonly=True),
        'date': fields.datetime('Date', required=True, readonly=True),
        'external_id': fields.char('External ID', size=64, readonly=True),
        'error_message': fields.text('Error Message', readonly=True),
        'resource': fields.serialized('External Data', readonly=True),
        'resource_text':fields.function(_get_resource, fnct_inv=_set_resource, type="text", string='External Data'),
        'args': fields.serialized('Args', readonly=True),
        'kwargs': fields.serialized('Kwargs', readonly=True),
    }

    _defaults = {
        "date": lambda *a: time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
    }

    def _log_base(self, cr, uid, model, action, state=None, res_id=None,
                  external_id=None,exception=None, resource=None,
                  args=None, kwargs=None):

        context = kwargs.get('context')
        existing_line_id = context.get('retry_report_line_id', False)
        report_id = context['report_id']

        # connection object can not be kept in text indeed
        # FIXME : see if we have some problem with other objects
        # and maybe remove from the conect all objects
        # which are not string, boolean, list, dict, integer, float or ?
        if existing_line_id:
            self.write(cr, uid,
                           existing_line_id,
                           {'state': state,
                            'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
                            'error_message': exception and str(exception) or False,
                            'args': args,
                            'kwargs': kwargs,
                            })
        else:
            existing_line_id = self.create(cr, uid, {
                            'report_id': report_id,
                            'state': state,
                            'res_model': model,
                            'action': action,
                            'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
                            'res_id': res_id,
                            'external_id': external_id,
                            'error_message': exception and str(exception) or False,
                            'resource': resource,
                            'args': args,
                            'kwargs': kwargs,
                        })
        return existing_line_id

    def retry(self, cr, uid, ids, context=None):
        if isinstance(ids, int):
            ids = [ids]

        for log in self.browse(cr, uid, ids, context=context):
            method = getattr(self.pool.get(log.kwargs['context']['report_line_based_on']), log.action)
            args = log.args
            kwargs = log.kwargs
            sync_from_object = self.pool.get(log.report_id.object_related).browse(cr, uid, log.report_id.res_id, context=context)
            external_session = ExternalSession(log.report_id.referential_id, sync_from_object)
            import pdb;pdb.set_trace()
            resource = log.resource
            if not kwargs.get('context', False):
                kwargs['context']={}

            # keep the id of the line to update it with the result
            kwargs['context']['retry_report_line_id'] = log.id

            method(cr, uid, external_session, resource, *args, **kwargs)
        return True

    def aggregate_actions(self, cr, uid, ids, context=None):
        res = {}
        for line in self.browse(cr, uid, ids, context=context):
            state = line.state
            model = line.res_model
            action = line.action

            if not res.get((state, model, action), False):
                res[(state, model, action)] = 0
            res[(state, model, action)] += 1

        return res

external_report_lines()
<commit_msg>[FIX] fix func_inv for resource_text in report<commit_after># -*- encoding: utf-8 -*-
##############################################################################
#
#    Author Guewen Baconnier. Copyright Camptocamp SA
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU 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 General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import time
import pooler
import logging
from osv import osv, fields
from tools.translate import _
from tools.safe_eval import safe_eval
from tools import DEFAULT_SERVER_DATETIME_FORMAT
import simplejson
from base_external_referentials.external_osv import ExternalSession

class external_report(osv.osv):
    _name = 'external.report'
    _description = 'External Report'
    _order = 'end_date desc'

    _columns = {
        'name': fields.char('Action', size=32, required=True,
                            readonly=True),
        'object_name': fields.char('Ressource Name', size=64, required=True,
                            readonly=True),
        'object_related': fields.char('Report Related To', size=64, required=True,
                            readonly=True),
        'object_related_description': fields.char('Report Related To', size=64, required=True,
                            readonly=True),
        'res_id': fields.integer('Ressource id', required=True, readonly=True),
        'method': fields.char('Method', size=64, required=True,
                           readonly=True,
                           help="Method linked to the report"),
        'start_date': fields.datetime('Last Start Date', readonly=True),
        'end_date': fields.datetime('Last End Date', readonly=True),
        'referential_id': fields.many2one('external.referential',
                                                   'External Referential',
                                                   required=True,
                                                   readonly=True),
        'line_ids': fields.one2many('external.report.line',
                                    'report_id', 'Report Lines'),
        'failed_line_ids': fields.one2many('external.report.line',
                                           'report_id',
                                           'Failed Report Lines',
                                           domain=[('state', '!=', 'success')]),
        'history_ids': fields.one2many('external.report.history',
                                       'report_id', 'History'),
    }

    def get_report_filter(self, cr, uid, method, object, context=None):
        return [
            ('method', '=', method),
            ('res_id', '=', object.id),
            ('object_related', '=', object._name),
        ]

    def get_report(self, cr, uid, method, object, context=None):
        report_id = False
        filter = self.get_report_filter(cr, uid, method, object, context=context)
        report = self.search(cr, uid, filter, context=context)
        if report:
            report_id = report[0]
        return report_id

    def _clean_successful_lines(self, cr, uid, report_id, context=None):
        lines_obj = self.pool.get('external.report.line')
        line_ids = lines_obj.search(cr, uid,
                                    [('report_id', '=', report_id),
                                    ('state', '=', 'success')],
                                    context=context)
        lines_obj.unlink(cr, uid, line_ids, context=context)
        return True

    def retry_failed_lines(self, cr, uid, ids, context=None):
        logging.getLogger('external_synchro').info("retry the failed lines of the reports ids %s" % (ids,))
        if isinstance(ids, int):
            ids = [ids]
        if not context:
            context={}
        context['origin'] = 'retry'
        for report in self.read(cr, uid, ids, ['failed_line_ids'], context=context):
            failed_line_ids = report['failed_line_ids']
            if failed_line_ids:
                context['report_id'] = report['id']
                self.pool.get('external.report.line').retry(cr, uid, failed_line_ids, context=context)
        return True

    def _prepare_start_report(self, cr, uid, method, object, context=None):
        return {'name': method.replace('_', ' ').strip(),
                'object_name': getattr(object, object._rec_name),
                'object_related': object._name,
                'object_related_description': object._description,
                'res_id': object.id,
                'method': method,
                'referential_id': object.referential_id.id,
                'start_date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),}

    def start_report(self, cr, uid, id=None, method=None,
                     object=None, context=None):
        """ Start a report, use the report with the id in the parameter
        if given. Otherwise, try to find the report which have the same method
         and object (we use the same report to avoid a
         multiplication of reports) If nothing is found, it create a new report
        """

        if not id and (not method or not object):
            raise Exception('No reference to create the report!')
        if id:
            report_id = id
        else:
            report_id = self.get_report(cr, uid, method, object, context)

        log_cr = pooler.get_db(cr.dbname).cursor()
        try:
            if report_id:
                self.write(log_cr, uid, report_id,
                           {'start_date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
                            'end_date': False},
                           context=context)
                # clean successful lines of the last report
                self._clean_successful_lines(log_cr, uid, report_id, context)
            else:
                report_id = self.create(
                    log_cr, uid,
                    self._prepare_start_report(
                        cr, uid, method, object, context=context),
                    context=context)
            log_cr.commit()

        finally:
            log_cr.close()

        return report_id

    def end_report(self, cr, uid, id, context=None):
        """ Create history lines based on lines
        Successful lines are cleaned at each start of a report
        so we historize their aggregation.
        """
        log_cr = pooler.get_db(cr.dbname).cursor()
        report = self.browse(log_cr, uid, id, context=context)
        lines_obj = self.pool.get('external.report.line')
        history_obj = self.pool.get('external.report.history')
        try:
            line_ids = lines_obj.search(log_cr, uid,
                                     [('report_id', '=', id),
                                     '|', ('write_date', '>', report.start_date),
                                     ('create_date', '>', report.start_date)],
                                     context=context)

            grouped_lines = lines_obj.aggregate_actions(log_cr, uid,
                                                        line_ids,
                                                        context)

            for line in grouped_lines:
                history_obj.create(log_cr, uid,
                                   {
                        'report_id': id,
                        'res_model': line[1],
                        'action': line[2],
                        'count': grouped_lines[line],
                        'user_id': uid,
                        'state': line[0],
                        'origin': context.get('origin', False),
                    }, context=context)

            self.write(log_cr, uid, id,
                       {'end_date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)},
                       context=context)

            log_cr.commit()
        finally:
            log_cr.close()
        return id

external_report()

class external_report_history(osv.osv):
    _name = 'external.report.history'
    _description = 'External Report History'
    _rec_name = 'report_id'
    _order = 'date desc'

    _columns = {
        'report_id': fields.many2one('external.report',
                                              'External Report',
                                              required=True,
                                              readonly=True,
                                              ondelete='cascade'),
        'date': fields.datetime('End Date', required=True, readonly=True),
        'res_model': fields.char('Resource Object', size=64,
                                 required=True, readonly=True),
        'action': fields.char('Action', size=64, required=True, readonly=True),
        'count': fields.integer('Count', readonly=True),
        'user_id': fields.many2one('res.users', 'User', required=True, readonly=True),
        'state': fields.selection((('success', 'Success'),
                                   ('fail', 'Failed')),
                                   'Status', required=True, readonly=True),
        'origin': fields.char('Origin', size=64, readonly=True),
    }

    _defaults = {
        "date": lambda *a: time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
    }

external_report_history()

class external_report_lines(osv.osv):
    _name = 'external.report.line'
    _description = 'External Report Lines'
    _rec_name = 'res_id'
    _order = 'date desc'

    def _get_resource(self, cr, uid, ids, field_name, arg, context=None):
        res = {}
        for report_line in self.browse(cr, uid, ids, context=context):
            res[report_line.id] = simplejson.dumps(report_line.resource)
        return res

    def _set_resource(self, cr, uid, ids, field_name, field_value, arg, context=None):
        res = {}
        for report_line in self.browse(cr, uid, ids, context=context):
            res[report_line.id] = simplejson.loads(report_line.resource)
        return res

    _columns = {
        'report_id': fields.many2one('external.report',
                                              'External Report',
                                              required=True,
                                              readonly=True,
                                              ondelete='restrict'),
        'state': fields.selection((('success', 'Success'),
                                   ('fail', 'Failed')),
                                   'Status', required=True, readonly=True),
        'res_model': fields.char('Resource Object', size=64,
                                 required=True, readonly=True),
        'res_id': fields.integer('Resource Id', readonly=True),
        'action': fields.char('Action', size=32, required=True, readonly=True),
        'date': fields.datetime('Date', required=True, readonly=True),
        'external_id': fields.char('External ID', size=64, readonly=True),
        'error_message': fields.text('Error Message', readonly=True),
        'resource': fields.serialized('External Data', readonly=True),
        'resource_text':fields.function(_get_resource, fnct_inv=_set_resource, type="text", string='External Data'),
        'args': fields.serialized('Args', readonly=True),
        'kwargs': fields.serialized('Kwargs', readonly=True),
    }

    _defaults = {
        "date": lambda *a: time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
    }

    def _log_base(self, cr, uid, model, action, state=None, res_id=None,
                  external_id=None,exception=None, resource=None,
                  args=None, kwargs=None):

        context = kwargs.get('context')
        existing_line_id = context.get('retry_report_line_id', False)
        report_id = context['report_id']

        # connection object can not be kept in text indeed
        # FIXME : see if we have some problem with other objects
        # and maybe remove from the conect all objects
        # which are not string, boolean, list, dict, integer, float or ?
        if existing_line_id:
            self.write(cr, uid,
                           existing_line_id,
                           {'state': state,
                            'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
                            'error_message': exception and str(exception) or False,
                            'args': args,
                            'kwargs': kwargs,
                            })
        else:
            existing_line_id = self.create(cr, uid, {
                            'report_id': report_id,
                            'state': state,
                            'res_model': model,
                            'action': action,
                            'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
                            'res_id': res_id,
                            'external_id': external_id,
                            'error_message': exception and str(exception) or False,
                            'resource': resource,
                            'args': args,
                            'kwargs': kwargs,
                        })
        return existing_line_id

    def retry(self, cr, uid, ids, context=None):
        if isinstance(ids, int):
            ids = [ids]

        for log in self.browse(cr, uid, ids, context=context):
            method = getattr(self.pool.get(log.kwargs['context']['report_line_based_on']), log.action)
            args = log.args
            kwargs = log.kwargs
            sync_from_object = self.pool.get(log.report_id.object_related).browse(cr, uid, log.report_id.res_id, context=context)
            external_session = ExternalSession(log.report_id.referential_id, sync_from_object)
            import pdb;pdb.set_trace()
            resource = log.resource
            if not kwargs.get('context', False):
                kwargs['context']={}

            # keep the id of the line to update it with the result
            kwargs['context']['retry_report_line_id'] = log.id

            method(cr, uid, external_session, resource, *args, **kwargs)
        return True

    def aggregate_actions(self, cr, uid, ids, context=None):
        res = {}
        for line in self.browse(cr, uid, ids, context=context):
            state = line.state
            model = line.res_model
            action = line.action

            if not res.get((state, model, action), False):
                res[(state, model, action)] = 0
            res[(state, model, action)] += 1

        return res

external_report_lines()
<|endoftext|>


<commit_before>from basket.news.middleware import is_ip_address

def test_is_ip_address():
    assert is_ip_address('1.2.3.4')
    assert is_ip_address('192.168.1.1')
    assert not is_ip_address('basket.mozilla.org')
    assert not is_ip_address('42.basket.mozilla.org')
<commit_msg>Add tests for enforce hostname middleware<commit_after>from django.test import RequestFactory, override_settings

from mock import Mock

from basket.news.middleware import EnforceHostnameMiddleware, is_ip_address

def test_is_ip_address():
    assert is_ip_address('1.2.3.4')
    assert is_ip_address('192.168.1.1')
    assert not is_ip_address('basket.mozilla.org')
    assert not is_ip_address('42.basket.mozilla.org')

@override_settings(DEBUG=False, ENFORCE_HOSTNAME=['basket.mozilla.org'])
def test_enforce_hostname_middleware():
    get_resp_mock = Mock()
    mw = EnforceHostnameMiddleware(get_resp_mock)
    req = RequestFactory().get('/', HTTP_HOST='basket.mozilla.org')
    resp = mw(req)
    get_resp_mock.assert_called_once_with(req)

    get_resp_mock.reset_mock()
    req = RequestFactory().get('/', HTTP_HOST='basket.allizom.org')
    resp = mw(req)
    get_resp_mock.assert_not_called()
    assert resp.status_code == 301
    assert resp['location'] == 'http://basket.mozilla.org/'

    # IP address should not redirect
    get_resp_mock.reset_mock()
    req = RequestFactory().get('/', HTTP_HOST='123.123.123.123')
    resp = mw(req)
    get_resp_mock.assert_called_once_with(req)

    # IP with port should also work
    get_resp_mock.reset_mock()
    req = RequestFactory().get('/', HTTP_HOST='1.2.3.4:12345')
    resp = mw(req)
    get_resp_mock.assert_called_once_with(req)
<|endoftext|>


<commit_before>#!/usr/bin/env python3
#
# This Python 3 program checks for a change in battery level since the last
# time this program was run, and sends an alert when the battery level
# decreases below a custom threshold.

import configparser
import os
import subprocess
import sys
import time

# Custom modules:
from logger import Logger
from slack_messenger import SlackMessenger

# Change the values in this array to modify at what percentages the
# notification should be sent.
alert_percentages = [20, 50]

def report_battery_level(slack_config, battery_level):
    if slack_config.getboolean("reporting") is True:
        slack_messenger = SlackMessenger(
                slack_config["report_slack_token"],
                slack_config["report_channel"],
                slack_config["report_slackbot_name"]
        )
        slack_messenger.message(
                "Current laptop battery level: " + str(battery_level) + "%."
        )

def alert_battery_level(slack_config, alert_level):
    slack_messenger = SlackMessenger(
            slack_config["alert_slack_token"],
            slack_config["alert_channel"],
            slack_config["alert_slackbot_name"]
    )
    slack_messenger.notify(
            slack_config["alert_list"],
            "Laptop battery is below " + str(alert_level) + "%."
    )

def run_cmd(args):
    '''Executes a set of arguments in the command line.

    Arguments:
        args -- Arguments to execute.
    Returns:
        string -- Output (stdout) from the execution.
    '''
    return subprocess.run(args, stdout=subprocess.PIPE).stdout.decode("utf-8")

def find_line_with(lines, str):
    '''Returns the first line with the given search term.

    Arguments:
        lines (string) -- Set of lines, separated by newlines.
        str (string) -- The given search term.
    Returns:
        string -- The first occurrence of a line containing the search term.s
    '''
    for line in lines.split("\n"):
        if str in line:
            return line

def get_battery_percentage():
    '''Returns the current battery level in percent.

    Returns:
        int -- The current battery level in percent.
    '''
    # Parse power data from OS
    power_files = run_cmd(["upower", "-e"])
    power_file = find_line_with(power_files, "BAT")

    power_data = run_cmd(["upower", "-i", power_file])
    percentage_line = find_line_with(power_data, "percentage")

    # Parse percentage from string with various characters into number
    current_percent = ""
    for char in percentage_line:
        if char.isdigit():
            current_percent += char

    return int(current_percent)

def main():
    location = os.path.realpath(
            os.path.join(os.getcwd(), os.path.dirname(__file__)))
    config_filename = os.path.join(location, "battery_notifier.cfg")
    config = configparser.ConfigParser()
    config.read(config_filename)
    slack_config = config["Slack"]

    current_percent = get_battery_percentage()

    Logger.debug("Current battery: " + str(current_percent) + "%")
    report_battery_level(slack_config, current_percent)

    battery_level_filename = "/tmp/last_battery_level"

    # Open file for reading and writing, or create one if it does not exist
    try:
        # Read and write existing file
        file = open(battery_level_filename, mode='r+')
    except IOError:
        Logger.debug("Battery state file does not exist; creating new file.")

        # Read and write new file
        file = open(battery_level_filename, mode='x+')
        file.write(str(current_percent))
        file.flush()
        file.seek(0)  # Rewind to beginning of file

    file_contents = file.read()
    try:
        last_percent = int(file_contents)
    except ValueError:
        Logger.error("Last battery level could not be parsed. Contents: ")
        Logger.error(file.read(file_contents))
        Logger.error("Recreating battery state file.")
        last_percent = current_percent

    # # Tester
    # current_percent = 0
    # last_percent = 100

    if current_percent < last_percent:
        alert_percentages.sort()  # Only alert for the lowest percentage
        for i in alert_percentages:
            if current_percent <= i and i < last_percent:
                Logger.info("Alert: Battery is below " + str(i) + "%.")
                alert_battery_level(slack_config, i)
                break;

    # Replace previous percentage with new percentage
    file.seek(0)
    file.write(str(current_percent))
    file.truncate()

    file.close()

if __name__ == "__main__":
    try:
        main()
    except Exception as e:
        Logger.error(
                "Script experienced an error and could not complete: " + str(e)
        )
<commit_msg>[Battery Notifier] Send error alert on exception<commit_after>#!/usr/bin/env python3
#
# This Python 3 program checks for a change in battery level since the last
# time this program was run, and sends an alert when the battery level
# decreases below a custom threshold.

import configparser
import os
import subprocess
import sys
import time

# Custom modules:
from logger import Logger
from slack_messenger import SlackMessenger

# Change the values in this array to modify at what percentages the
# notification should be sent.
alert_percentages = [20, 50]

def report_battery_level(slack_config, battery_level):
    if slack_config.getboolean("reporting") is True:
        slack_messenger = SlackMessenger(
                slack_config["report_slack_token"],
                slack_config["report_channel"],
                slack_config["report_slackbot_name"]
        )
        slack_messenger.message(
                "Current laptop battery level: " + str(battery_level) + "%."
        )

def alert_battery_level(slack_config, alert_level):
    slack_messenger = SlackMessenger(
            slack_config["alert_slack_token"],
            slack_config["alert_channel"],
            slack_config["alert_slackbot_name"]
    )
    slack_messenger.notify(
            slack_config["alert_list"],
            "Laptop battery is below " + str(alert_level) + "%."
    )

def alert_error(slack_config):
    slack_messenger = SlackMessenger(
            slack_config["alert_slack_token"],
            slack_config["alert_channel"],
            slack_config["alert_slackbot_name"]
    )
    slack_messenger.notify(
            slack_config["alert_list"],
            "Internal error for Battery Notifier, please check the logs."
    )

def run_cmd(args):
    '''Executes a set of arguments in the command line.

    Arguments:
        args -- Arguments to execute.
    Returns:
        string -- Output (stdout) from the execution.
    '''
    return subprocess.run(args, stdout=subprocess.PIPE).stdout.decode("utf-8")

def find_line_with(lines, str):
    '''Returns the first line with the given search term.

    Arguments:
        lines (string) -- Set of lines, separated by newlines.
        str (string) -- The given search term.
    Returns:
        string -- The first occurrence of a line containing the search term.s
    '''
    for line in lines.split("\n"):
        if str in line:
            return line

def get_battery_percentage():
    '''Returns the current battery level in percent.

    Returns:
        int -- The current battery level in percent.
    '''
    # Parse power data from OS
    power_files = run_cmd(["upower", "-e"])
    power_file = find_line_with(power_files, "BAT")

    power_data = run_cmd(["upower", "-i", power_file])
    percentage_line = find_line_with(power_data, "percentage")

    # Parse percentage from string with various characters into number
    current_percent = ""
    for char in percentage_line:
        if char.isdigit():
            current_percent += char

    return int(current_percent)

def main(config):
    slack_config = config["Slack"]

    current_percent = get_battery_percentage()

    Logger.debug("Current battery: " + str(current_percent) + "%")
    report_battery_level(slack_config, current_percent)

    battery_level_filename = "/tmp/last_battery_level"

    # Open file for reading and writing, or create one if it does not exist
    try:
        # Read and write existing file
        file = open(battery_level_filename, mode='r+')
    except IOError:
        Logger.debug("Battery state file does not exist; creating new file.")

        # Read and write new file
        file = open(battery_level_filename, mode='x+')
        file.write(str(current_percent))
        file.flush()
        file.seek(0)  # Rewind to beginning of file

    file_contents = file.read()
    try:
        last_percent = int(file_contents)
    except ValueError:
        Logger.error("Last battery level could not be parsed. Contents: ")
        Logger.error(file.read(file_contents))
        Logger.error("Recreating battery state file.")
        last_percent = current_percent

    # # Tester
    # current_percent = 0
    # last_percent = 100

    if current_percent < last_percent:
        alert_percentages.sort()  # Only alert for the lowest percentage
        for i in alert_percentages:
            if current_percent <= i and i < last_percent:
                Logger.info("Alert: Battery is below " + str(i) + "%.")
                alert_battery_level(slack_config, i)
                break;

    # Replace previous percentage with new percentage
    file.seek(0)
    file.write(str(current_percent))
    file.truncate()

    file.close()

if __name__ == "__main__":
    location = os.path.realpath(
            os.path.join(os.getcwd(), os.path.dirname(__file__)))
    config_filename = os.path.join(location, "battery_notifier.cfg")
    config = configparser.ConfigParser()
    config.read(config_filename)
    try:
        main(config)
    except Exception as e:
        alert_error(config["Slack"])
        raise
<|endoftext|>


<commit_before>from zope.interface import implements, Interface, Attribute
from Products.Five import BrowserView

#from bda.plone.cart.interfaces.ICartDataProvider import  get_data_provider
from bda.plone.shopviews import shopviewsMessageFactory  as _

from Products.CMFCore.utils import getToolByName

class IColorsView(Interface):
    """
    Redirect  view interface
    """

class IProductsView(Interface):
    """
    Products  view interface
    """

    #def currency(self):
    #    """Get the currency"""

    def test():
        """ test method"""

    def all_keywords():
        """ get all keywords in folder so we can sort on them """

    def colors():
        """ get (all) color (field) in your content type for folder """

    def variations():
        """ get (all) variation (field) in your content type for folder """

class ColorsView(BrowserView):
    """
    Browser view that does the following.
    - redirects to parent folder of product.
    - sets color to context's color
    - uses this in the folder view
    """
    implements(IColorsView)

    def __call__(self):
        request = self.request
        color = self.context.color
        redirect_url = self.context.aq_parent.absolute_url() + '/productlist_view?color=' + color
        #return self.context.redirect(redirect_url)
        return redirect_url

class ProductsView(BrowserView):
    """
    Products browser view
    """
    implements(IProductsView)

    #property
    #def currency(self):
    #    return self.data_provider.currency

    def test(self):
        """
        test method
        """

        dummy = _(u'a dummy string')
        return {'dummy': dummy}

    def find_objects(self):
        #not working at the moment
        #so the same code is 3 times below
        catalog = getToolByName(self, 'portal_catalog')
        if context.is_folderish:
            folder_path = '/'.join(context.getPhysicalPath())
        else:
            folder_path = '/'.join(context.aq_parent.getPhysicalPath())
        results = []
        results = catalog.searchResults(path={'query': folder_path})
        return results

    @property
    def all_keywords(self):
        #results = self.find_objects
        context = self.context
        catalog = getToolByName(self, 'portal_catalog')
        import pdb; pdb.set_trace()
        if context.is_folderish:
            folder_path = '/'.join(context.getPhysicalPath())
        else:
            folder_path = '/'.join(context.aq_parent.getPhysicalPath())
        results = []
        results = catalog.searchResults(path={'query': folder_path})

        uniques = ""
        tags = set()
        for item in results:
            tags.update(item.Subject)
        return sorted(tags)

    @property
    def variations(self):
        #results = self.find_objects
        context = self.context
        catalog = getToolByName(self, 'portal_catalog')
        if context.is_folderish:
            folder_path = '/'.join(context.getPhysicalPath())
        else:
            folder_path = '/'.join(context.aq_parent.getPhysicalPath())
        results = []
        results = catalog.searchResults(path={'query': folder_path})

        uniques = ""
        tags = set()
        for item in results:
            try:
                tags.update(item.variation)
            except:
                pass
        return sorted(tags)

    @property
    def colors(self):
        #results = self.find_objects
        context = self.context
        catalog = getToolByName(self, 'portal_catalog')
        if context.is_folderish():
            folder_path = '/'.join(context.getPhysicalPath())
        else:
            folder_path = '/'.join(context.aq_parent.getPhysicalPath())
        results = []
        results = catalog.searchResults(path={'query': folder_path})

        uniques = ""
        tags = set()
        for item in results:
            try:
                tags.update(item.color)
            except:
                pass
        return sorted(tags)<commit_msg>check for is folderish (thanks moo)<commit_after>from zope.interface import implements, Interface, Attribute
from Products.Five import BrowserView

#from bda.plone.cart.interfaces.ICartDataProvider import  get_data_provider
from bda.plone.shopviews import shopviewsMessageFactory  as _

from Products.CMFCore.utils import getToolByName

class IColorsView(Interface):
    """
    Redirect  view interface
    """

class IProductsView(Interface):
    """
    Products  view interface
    """

    #def currency(self):
    #    """Get the currency"""

    def test():
        """ test method"""

    def all_keywords():
        """ get all keywords in folder so we can sort on them """

    def colors():
        """ get (all) color (field) in your content type for folder """

    def variations():
        """ get (all) variation (field) in your content type for folder """

class ColorsView(BrowserView):
    """
    Browser view that does the following.
    - redirects to parent folder of product.
    - sets color to context's color
    - uses this in the folder view
    """
    implements(IColorsView)

    def __call__(self):
        request = self.request
        color = self.context.color
        redirect_url = self.context.aq_parent.absolute_url() + '/productlist_view?color=' + color
        #return self.context.redirect(redirect_url)
        return redirect_url

class ProductsView(BrowserView):
    """
    Products browser view
    """
    implements(IProductsView)

    #property
    #def currency(self):
    #    return self.data_provider.currency

    def test(self):
        """
        test method
        """

        dummy = _(u'a dummy string')
        return {'dummy': dummy}

    def find_objects(self):
        #not working at the moment
        #so the same code is 3 times below
        catalog = getToolByName(self, 'portal_catalog')
        if context.is_folderish:
            folder_path = '/'.join(context.getPhysicalPath())
        else:
            folder_path = '/'.join(context.aq_parent.getPhysicalPath())
        results = []
        results = catalog.searchResults(path={'query': folder_path})
        return results

    @property
    def all_keywords(self):
        #results = self.find_objects
        context = self.context
        catalog = getToolByName(self, 'portal_catalog')
        if IFolderish.isProvidedBy(context.aq_base):
            folder_path = '/'.join(context.getPhysicalPath())
        else:
            folder_path = '/'.join(context.aq_parent.getPhysicalPath())
        results = []
        results = catalog.searchResults(path={'query': folder_path})

        uniques = ""
        tags = set()
        for item in results:
            tags.update(item.Subject)
        return sorted(tags)

    @property
    def variations(self):
        #results = self.find_objects
        context = self.context
        catalog = getToolByName(self, 'portal_catalog')
        if IFolderish.isProvidedBy(context.aq_base):
            folder_path = '/'.join(context.getPhysicalPath())
        else:
            folder_path = '/'.join(context.aq_parent.getPhysicalPath())
        results = []
        results = catalog.searchResults(path={'query': folder_path})

        uniques = ""
        tags = set()
        for item in results:
            try:
                tags.update(item.variation)
            except:
                pass
        return sorted(tags)

    @property
    def colors(self):
        #results = self.find_objects
        context = self.context
        catalog = getToolByName(self, 'portal_catalog')
        if IFolderish.isProvidedBy(context.aq_base):
            folder_path = '/'.join(context.getPhysicalPath())
        else:
            folder_path = '/'.join(context.aq_parent.getPhysicalPath())
        results = []
        results = catalog.searchResults(path={'query': folder_path})

        uniques = ""
        tags = set()
        for item in results:
            try:
                tags.update(item.color)
            except:
                pass
        return sorted(tags)<|endoftext|>


<commit_before>from driver_base import *
import sys
import time
import os
os.sys.path.insert(0,os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import log
try:
    import serial, serial.tools.list_ports
except ImportError as e:
    error = "Please install pyserial 2.7+! pip install pyserial"
    log.logger.error(error)
    raise ImportError(error)

class BiblioSerialError(Exception):
    pass

class CMDTYPE:
    SETUP_DATA = 1 #config data (LED type, SPI speed, num LEDs)
    PIXEL_DATA = 2 #raw pixel data will be sent as [R1,G1,B1,R2,G2,B2,...]
    BRIGHTNESS = 3 #data will be single 0-255 brightness value, length must be 0x00,0x01

class RETURN_CODES:
    SUCCESS = 255 #All is well
    REBOOT = 42 #Device reboot needed after configuration
    ERROR = 0 #Generic error
    ERROR_SIZE = 1 #Data receieved does not match given command length
    ERROR_UNSUPPORTED = 2 #Unsupported command
    ERROR_PIXEL_COUNT = 3 #Too many pixels for device

class LEDTYPE:
    GENERIC = 0 #Use if the serial device only supports one chipset
    LPD8806 = 1
    WS2801  = 2
    #These are all the same
    WS2811 = 3
    WS2812 = 3
    WS2812B = 3
    NEOPIXEL = 3
    APA104 = 3
    #400khz variant of above
    WS2811_400 = 4

    TM1809 = 5
    TM1804 = 5
    TM1803 = 6
    UCS1903 = 7
    SM16716 = 8
    APA102 = 9
    LPD1886 = 10
    P9813 = 11

class DriverSerial(DriverBase):
    """Main driver for Serial based LED strips"""

    def __init__(self, type, num, dev="", c_order = ChannelOrder.RGB, SPISpeed = 16, gamma = None, restart_timeout = 3):
        super(DriverSerial, self).__init__(num, c_order = c_order, gamma = gamma)

        if SPISpeed < 1 or SPISpeed > 24 or not (type == LEDTYPE.LPD8806 or type == LEDTYPE.WS2801 or type == LEDTYPE.SM16716):
            SPISpeed = 24

        self._SPISpeed = SPISpeed
        self._com = None
        self._type = type
        self.dev = dev

        resp = self._connect()
        if resp == RETURN_CODES.REBOOT: #reboot needed
            log.logger.info("Reconfigure and reboot needed, waiting for controller to restart...")
            self._com.close()
            time.sleep(restart_timeout)
            resp = self._connect()
            if resp != RETURN_CODES.SUCCESS:
                self._printError(resp)
            else:
                log.logger.info("Reconfigure success!")
        elif resp != RETURN_CODES.SUCCESS:
            self._printError(resp)

    def _printError(self, error):
        msg = "Unknown error occured."
        if error == RETURN_CODES.ERROR_SIZE:
            msg = "Data packet size incorrect."
        elif error == RETURN_CODES.ERROR_UNSUPPORTED:
            msg = "Unsupported configuration attempted."
        elif error == RETURN_CODES.ERROR_PIXEL_COUNT:
            msg = "Too many pixels specified for device."

        log.logger.error(msg)
        raise BiblioSerialError(msg)

    def _comError(self):
        error = "There was an unknown error communicating with the device."
        log.logger.error(error)
        raise IOError(error)

    def _connect(self):
        try:
            if(self.dev == ""):
                com_list = serial.tools.list_ports.grep("4242:8037")
                try:
                    port = com_list.next()
                    self.dev = port[0]
                    log.logger.info( "Using COM Port: {:}".format(self.dev))
                except StopIteration:
                    pass

            try:
                self._com =  serial.Serial(self.dev, timeout=5)
            except serial.SerialException as e:
                ports = list(serial.tools.list_ports.comports())
                error = "Invalid port specified. No COM ports available."
                if len(ports) > 0:
                    p_list = []
                    for p in ports:
                        p_list.append(p[0] + " - " + p[1])

                    error = "Invalid port specified. Try using one of: \n" + "\n".join(p_list)
                log.logger.info(error)
                raise BiblioSerialError(error)

            packet = self._generateHeader(CMDTYPE.SETUP_DATA, 4)
            packet.append(self._type) #set strip type
            packet.append(self.bufByteCount & 0xFF) #set 1st byte of byteCount
            packet.append(self.bufByteCount >> 8) #set 2nd byte of byteCount
            packet.append(self._SPISpeed)
            self._com.write(packet)

            resp = self._com.read(1)
            if len(resp) == 0:
                self._comError()

            return ord(resp)

        except serial.SerialException as e:
            error = "Unable to connect to the device. Please check that it is connected and the correct port is selected."
            log.logger.exception(e)
            log.logger.error(error)
            raise e

    def _generateHeader(self, cmd, size):
        packet = bytearray()
        packet.append(cmd)
        packet.append(size & 0xFF)
        packet.append(size >> 8)
        return packet

    def setMasterBrightness(self, brightness):
        packet = self._generateHeader(CMDTYPE.BRIGHTNESS, 1)
        packet.append(brightness)
        self._com.write(packet)
        resp = ord(self._com.read(1))
        if resp != RETURN_CODES.SUCCESS:
            self._printError(resp)
            return False
        else:
            return True

    #Push new data to strand
    def update(self, data):
        count = self.bufByteCount
        packet = self._generateHeader(CMDTYPE.PIXEL_DATA, count)

        c_order = self.c_order

        self._fixData(data)

        packet.extend(self._buf)
        self._com.write(packet)

        resp = self._com.read(1)
        if len(resp) == 0:
                self._comError()
        if ord(resp) != RETURN_CODES.SUCCESS:
            self._printError(ord(resp))

        self._com.flushInput()

<commit_msg>updated VID/PID pair to reflect Allpixel firmware<commit_after>from driver_base import *
import sys
import time
import os
os.sys.path.insert(0,os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import log
try:
    import serial, serial.tools.list_ports
except ImportError as e:
    error = "Please install pyserial 2.7+! pip install pyserial"
    log.logger.error(error)
    raise ImportError(error)

class BiblioSerialError(Exception):
    pass

class CMDTYPE:
    SETUP_DATA = 1 #config data (LED type, SPI speed, num LEDs)
    PIXEL_DATA = 2 #raw pixel data will be sent as [R1,G1,B1,R2,G2,B2,...]
    BRIGHTNESS = 3 #data will be single 0-255 brightness value, length must be 0x00,0x01

class RETURN_CODES:
    SUCCESS = 255 #All is well
    REBOOT = 42 #Device reboot needed after configuration
    ERROR = 0 #Generic error
    ERROR_SIZE = 1 #Data receieved does not match given command length
    ERROR_UNSUPPORTED = 2 #Unsupported command
    ERROR_PIXEL_COUNT = 3 #Too many pixels for device

class LEDTYPE:
    GENERIC = 0 #Use if the serial device only supports one chipset
    LPD8806 = 1
    WS2801  = 2
    #These are all the same
    WS2811 = 3
    WS2812 = 3
    WS2812B = 3
    NEOPIXEL = 3
    APA104 = 3
    #400khz variant of above
    WS2811_400 = 4

    TM1809 = 5
    TM1804 = 5
    TM1803 = 6
    UCS1903 = 7
    SM16716 = 8
    APA102 = 9
    LPD1886 = 10
    P9813 = 11

class DriverSerial(DriverBase):
    """Main driver for Serial based LED strips"""

    def __init__(self, type, num, dev="", c_order = ChannelOrder.RGB, SPISpeed = 16, gamma = None, restart_timeout = 3):
        super(DriverSerial, self).__init__(num, c_order = c_order, gamma = gamma)

        if SPISpeed < 1 or SPISpeed > 24 or not (type == LEDTYPE.LPD8806 or type == LEDTYPE.WS2801 or type == LEDTYPE.SM16716):
            SPISpeed = 24

        self._SPISpeed = SPISpeed
        self._com = None
        self._type = type
        self.dev = dev

        resp = self._connect()
        if resp == RETURN_CODES.REBOOT: #reboot needed
            log.logger.info("Reconfigure and reboot needed, waiting for controller to restart...")
            self._com.close()
            time.sleep(restart_timeout)
            resp = self._connect()
            if resp != RETURN_CODES.SUCCESS:
                self._printError(resp)
            else:
                log.logger.info("Reconfigure success!")
        elif resp != RETURN_CODES.SUCCESS:
            self._printError(resp)

    def _printError(self, error):
        msg = "Unknown error occured."
        if error == RETURN_CODES.ERROR_SIZE:
            msg = "Data packet size incorrect."
        elif error == RETURN_CODES.ERROR_UNSUPPORTED:
            msg = "Unsupported configuration attempted."
        elif error == RETURN_CODES.ERROR_PIXEL_COUNT:
            msg = "Too many pixels specified for device."

        log.logger.error(msg)
        raise BiblioSerialError(msg)

    def _comError(self):
        error = "There was an unknown error communicating with the device."
        log.logger.error(error)
        raise IOError(error)

    def _connect(self):
        try:
            if(self.dev == ""):
                com_list = serial.tools.list_ports.grep("1D50:60AB")
                try:
                    port = com_list.next()
                    self.dev = port[0]
                    log.logger.info( "Using COM Port: {:}".format(self.dev))
                except StopIteration:
                    pass

            try:
                self._com =  serial.Serial(self.dev, timeout=5)
            except serial.SerialException as e:
                ports = list(serial.tools.list_ports.comports())
                error = "Invalid port specified. No COM ports available."
                if len(ports) > 0:
                    p_list = []
                    for p in ports:
                        p_list.append(p[0] + " - " + p[1])

                    error = "Invalid port specified. Try using one of: \n" + "\n".join(p_list)
                log.logger.info(error)
                raise BiblioSerialError(error)

            packet = self._generateHeader(CMDTYPE.SETUP_DATA, 4)
            packet.append(self._type) #set strip type
            packet.append(self.bufByteCount & 0xFF) #set 1st byte of byteCount
            packet.append(self.bufByteCount >> 8) #set 2nd byte of byteCount
            packet.append(self._SPISpeed)
            self._com.write(packet)

            resp = self._com.read(1)
            if len(resp) == 0:
                self._comError()

            return ord(resp)

        except serial.SerialException as e:
            error = "Unable to connect to the device. Please check that it is connected and the correct port is selected."
            log.logger.exception(e)
            log.logger.error(error)
            raise e

    def _generateHeader(self, cmd, size):
        packet = bytearray()
        packet.append(cmd)
        packet.append(size & 0xFF)
        packet.append(size >> 8)
        return packet

    def setMasterBrightness(self, brightness):
        packet = self._generateHeader(CMDTYPE.BRIGHTNESS, 1)
        packet.append(brightness)
        self._com.write(packet)
        resp = ord(self._com.read(1))
        if resp != RETURN_CODES.SUCCESS:
            self._printError(resp)
            return False
        else:
            return True

    #Push new data to strand
    def update(self, data):
        count = self.bufByteCount
        packet = self._generateHeader(CMDTYPE.PIXEL_DATA, count)

        c_order = self.c_order

        self._fixData(data)

        packet.extend(self._buf)
        self._com.write(packet)

        resp = self._com.read(1)
        if len(resp) == 0:
                self._comError()
        if ord(resp) != RETURN_CODES.SUCCESS:
            self._printError(ord(resp))

        self._com.flushInput()

<|endoftext|>


<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/>.
#
##############################################################################

from osv import fields, osv
import tools

TRANSLATION_TYPE = [
    ('field', 'Field'),
    ('model', 'Object'),
    ('rml', 'RML  (deprecated - use Report)'), # Pending deprecation - to be replaced by report!
    ('report', 'Report/Template'),
    ('selection', 'Selection'),
    ('view', 'View'),
    ('wizard_button', 'Wizard Button'),
    ('wizard_field', 'Wizard Field'),
    ('wizard_view', 'Wizard View'),
    ('xsl', 'XSL'),
    ('help', 'Help'),
    ('code', 'Code'),
    ('constraint', 'Constraint'),
    ('sql_constraint', 'SQL Constraint')
]

class ir_translation(osv.osv):
    _name = "ir.translation"
    _log_access = False

    def _get_language(self, cr, uid, context):
        lang_obj = self.pool.get('res.lang')
        lang_ids = lang_obj.search(cr, uid, [('translatable', '=', True)],
                context=context)
        langs = lang_obj.browse(cr, uid, lang_ids, context=context)
        res = [(lang.code, lang.name) for lang in langs]
        for lang_dict in tools.scan_languages():
            if lang_dict not in res:
                res.append(lang_dict)
        return res

    _columns = {
        'name': fields.char('Field Name', size=128, required=True),
        'res_id': fields.integer('Resource ID', select=True),
        'lang': fields.selection(_get_language, string='Language', size=16),
        'type': fields.selection(TRANSLATION_TYPE, string='Type', size=16, select=True),
        'src': fields.text('Source'),
        'value': fields.text('Translation Value'),
    }

    def _auto_init(self, cr, context={}):
        super(ir_translation, self)._auto_init(cr, context)

        # FIXME: there is a size limit on btree indexed values so we can't index src column with normal btree.
        cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('ir_translation_ltns',))
        if cr.fetchone():
            #temporarily removed: cr.execute('CREATE INDEX ir_translation_ltns ON ir_translation (name, lang, type, src)')
            cr.execute('DROP INDEX ir_translation_ltns')
            cr.commit()
        cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('ir_translation_lts',))
        if cr.fetchone():
            #temporarily removed: cr.execute('CREATE INDEX ir_translation_lts ON ir_translation (lang, type, src)')
            cr.execute('DROP INDEX ir_translation_lts')
            cr.commit()

        # add separate hash index on src (no size limit on values), as postgres 8.1+ is able to combine separate indexes
        cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('ir_translation_src_hash_idx',))
        if not cr.fetchone():
            cr.execute('CREATE INDEX ir_translation_src_hash_idx ON ir_translation using hash (src)')

        cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('ir_translation_ltn',))
        if not cr.fetchone():
            cr.execute('CREATE INDEX ir_translation_ltn ON ir_translation (name, lang, type)')
            cr.commit()

    @tools.cache(skiparg=3, multi='ids')
    def _get_ids(self, cr, uid, name, tt, lang, ids):
        translations = dict.fromkeys(ids, False)
        if ids:
            cr.execute('select res_id,value ' \
                    'from ir_translation ' \
                    'where lang=%s ' \
                        'and type=%s ' \
                        'and name=%s ' \
                        'and res_id IN %s',
                    (lang,tt,name,tuple(ids)))
            for res_id, value in cr.fetchall():
                translations[res_id] = value
        return translations

    def _set_ids(self, cr, uid, name, tt, lang, ids, value, src=None):
        # clear the caches
        tr = self._get_ids(cr, uid, name, tt, lang, ids)
        for res_id in tr:
            if tr[res_id]:
                self._get_source.clear_cache(cr.dbname, uid, name, tt, lang, tr[res_id])
        self._get_source.clear_cache(cr.dbname, uid, name, tt, lang)
        self._get_ids.clear_cache(cr.dbname, uid, name, tt, lang, ids)

        cr.execute('delete from ir_translation ' \
                'where lang=%s ' \
                    'and type=%s ' \
                    'and name=%s ' \
                    'and res_id IN %s',
                (lang,tt,name,tuple(ids),))
        for id in ids:
            self.create(cr, uid, {
                'lang':lang,
                'type':tt,
                'name':name,
                'res_id':id,
                'value':value,
                'src':src,
                })
        return len(ids)

    @tools.cache(skiparg=3)
    def _get_source(self, cr, uid, name, types, lang, source=None):
        """
        Returns the translation for the given combination of name, type, language
        and source. All values passed to this method should be unicode (not byte strings),
        especially ``source``.

        :param name: identification of the term to translate, such as field name (optional if source is passed)
        :param types: single string defining type of term to translate (see ``type`` field on ir.translation), or sequence of allowed types (strings)
        :param lang: language code of the desired translation
        :param source: optional source term to translate (should be unicode)
        :rtype: unicode
        :return: the request translation, or an empty unicode string if no translation was
                 found and `source` was not passed
        """
        # FIXME: should assert that `source` is unicode and fix all callers to always pass unicode
        # so we can remove the string encoding/decoding.
        if not lang:
            return u''
        if isinstance(types, basestring):
            types = (types,)
        if source:
            query = """SELECT value
                       FROM ir_translation
                       WHERE lang=%s
                        AND type in %s
                        AND src=%s"""
            params = (lang or '', types, source)
            if name:
                query += " AND name=%s"
                params += (tools.ustr(name),)
            cr.execute(query, params)
        else:
            cr.execute("""SELECT value
                          FROM ir_translation
                          WHERE lang=%s
                           AND type in %s
                           AND name=%s""",
                    (lang or '', types, tools.ustr(name)))
        res = cr.fetchone()
        trad = res and res[0] or u''
        if source and not trad:
            return tools.ustr(source)
        return trad

    def create(self, cursor, user, vals, context=None):
        if not context:
            context = {}
        ids = super(ir_translation, self).create(cursor, user, vals, context=context)
        for trans_obj in self.read(cursor, user, [ids], ['name','type','res_id','src','lang'], context=context):
            self._get_source.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], source=trans_obj['src'])
            self._get_ids.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], [trans_obj['res_id']])
        return ids

    def write(self, cursor, user, ids, vals, context=None):
        if not context:
            context = {}
        if isinstance(ids, (int, long)):
            ids = [ids]
        result = super(ir_translation, self).write(cursor, user, ids, vals, context=context)
        for trans_obj in self.read(cursor, user, ids, ['name','type','res_id','src','lang'], context=context):
            self._get_source.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], source=trans_obj['src'])
            self._get_ids.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], [trans_obj['res_id']])
        return result

    def unlink(self, cursor, user, ids, context=None):
        if not context:
            context = {}
        if isinstance(ids, (int, long)):
            ids = [ids]
        for trans_obj in self.read(cursor, user, ids, ['name','type','res_id','src','lang'], context=context):
            self._get_source.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], source=trans_obj['src'])
            self._get_ids.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], [trans_obj['res_id']])
        result = super(ir_translation, self).unlink(cursor, user, ids, context=context)
        return result

ir_translation()

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

<commit_msg>[FIX] ir.translation: coerce source terms into unicode, to avoid transmitting invalid UTF-8 bytes<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/>.
#
##############################################################################

from osv import fields, osv
import tools

TRANSLATION_TYPE = [
    ('field', 'Field'),
    ('model', 'Object'),
    ('rml', 'RML  (deprecated - use Report)'), # Pending deprecation - to be replaced by report!
    ('report', 'Report/Template'),
    ('selection', 'Selection'),
    ('view', 'View'),
    ('wizard_button', 'Wizard Button'),
    ('wizard_field', 'Wizard Field'),
    ('wizard_view', 'Wizard View'),
    ('xsl', 'XSL'),
    ('help', 'Help'),
    ('code', 'Code'),
    ('constraint', 'Constraint'),
    ('sql_constraint', 'SQL Constraint')
]

class ir_translation(osv.osv):
    _name = "ir.translation"
    _log_access = False

    def _get_language(self, cr, uid, context):
        lang_obj = self.pool.get('res.lang')
        lang_ids = lang_obj.search(cr, uid, [('translatable', '=', True)],
                context=context)
        langs = lang_obj.browse(cr, uid, lang_ids, context=context)
        res = [(lang.code, lang.name) for lang in langs]
        for lang_dict in tools.scan_languages():
            if lang_dict not in res:
                res.append(lang_dict)
        return res

    _columns = {
        'name': fields.char('Field Name', size=128, required=True),
        'res_id': fields.integer('Resource ID', select=True),
        'lang': fields.selection(_get_language, string='Language', size=16),
        'type': fields.selection(TRANSLATION_TYPE, string='Type', size=16, select=True),
        'src': fields.text('Source'),
        'value': fields.text('Translation Value'),
    }

    def _auto_init(self, cr, context={}):
        super(ir_translation, self)._auto_init(cr, context)

        # FIXME: there is a size limit on btree indexed values so we can't index src column with normal btree.
        cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('ir_translation_ltns',))
        if cr.fetchone():
            #temporarily removed: cr.execute('CREATE INDEX ir_translation_ltns ON ir_translation (name, lang, type, src)')
            cr.execute('DROP INDEX ir_translation_ltns')
            cr.commit()
        cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('ir_translation_lts',))
        if cr.fetchone():
            #temporarily removed: cr.execute('CREATE INDEX ir_translation_lts ON ir_translation (lang, type, src)')
            cr.execute('DROP INDEX ir_translation_lts')
            cr.commit()

        # add separate hash index on src (no size limit on values), as postgres 8.1+ is able to combine separate indexes
        cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('ir_translation_src_hash_idx',))
        if not cr.fetchone():
            cr.execute('CREATE INDEX ir_translation_src_hash_idx ON ir_translation using hash (src)')

        cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('ir_translation_ltn',))
        if not cr.fetchone():
            cr.execute('CREATE INDEX ir_translation_ltn ON ir_translation (name, lang, type)')
            cr.commit()

    @tools.cache(skiparg=3, multi='ids')
    def _get_ids(self, cr, uid, name, tt, lang, ids):
        translations = dict.fromkeys(ids, False)
        if ids:
            cr.execute('select res_id,value ' \
                    'from ir_translation ' \
                    'where lang=%s ' \
                        'and type=%s ' \
                        'and name=%s ' \
                        'and res_id IN %s',
                    (lang,tt,name,tuple(ids)))
            for res_id, value in cr.fetchall():
                translations[res_id] = value
        return translations

    def _set_ids(self, cr, uid, name, tt, lang, ids, value, src=None):
        # clear the caches
        tr = self._get_ids(cr, uid, name, tt, lang, ids)
        for res_id in tr:
            if tr[res_id]:
                self._get_source.clear_cache(cr.dbname, uid, name, tt, lang, tr[res_id])
        self._get_source.clear_cache(cr.dbname, uid, name, tt, lang)
        self._get_ids.clear_cache(cr.dbname, uid, name, tt, lang, ids)

        cr.execute('delete from ir_translation ' \
                'where lang=%s ' \
                    'and type=%s ' \
                    'and name=%s ' \
                    'and res_id IN %s',
                (lang,tt,name,tuple(ids),))
        for id in ids:
            self.create(cr, uid, {
                'lang':lang,
                'type':tt,
                'name':name,
                'res_id':id,
                'value':value,
                'src':src,
                })
        return len(ids)

    @tools.cache(skiparg=3)
    def _get_source(self, cr, uid, name, types, lang, source=None):
        """
        Returns the translation for the given combination of name, type, language
        and source. All values passed to this method should be unicode (not byte strings),
        especially ``source``.

        :param name: identification of the term to translate, such as field name (optional if source is passed)
        :param types: single string defining type of term to translate (see ``type`` field on ir.translation), or sequence of allowed types (strings)
        :param lang: language code of the desired translation
        :param source: optional source term to translate (should be unicode)
        :rtype: unicode
        :return: the request translation, or an empty unicode string if no translation was
                 found and `source` was not passed
        """
        # FIXME: should assert that `source` is unicode and fix all callers to always pass unicode
        # so we can remove the string encoding/decoding.
        if not lang:
            return u''
        if isinstance(types, basestring):
            types = (types,)
        if source:
            query = """SELECT value
                       FROM ir_translation
                       WHERE lang=%s
                        AND type in %s
                        AND src=%s"""
            params = (lang or '', types, tools.ustr(source))
            if name:
                query += " AND name=%s"
                params += (tools.ustr(name),)
            cr.execute(query, params)
        else:
            cr.execute("""SELECT value
                          FROM ir_translation
                          WHERE lang=%s
                           AND type in %s
                           AND name=%s""",
                    (lang or '', types, tools.ustr(name)))
        res = cr.fetchone()
        trad = res and res[0] or u''
        if source and not trad:
            return tools.ustr(source)
        return trad

    def create(self, cursor, user, vals, context=None):
        if not context:
            context = {}
        ids = super(ir_translation, self).create(cursor, user, vals, context=context)
        for trans_obj in self.read(cursor, user, [ids], ['name','type','res_id','src','lang'], context=context):
            self._get_source.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], source=trans_obj['src'])
            self._get_ids.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], [trans_obj['res_id']])
        return ids

    def write(self, cursor, user, ids, vals, context=None):
        if not context:
            context = {}
        if isinstance(ids, (int, long)):
            ids = [ids]
        result = super(ir_translation, self).write(cursor, user, ids, vals, context=context)
        for trans_obj in self.read(cursor, user, ids, ['name','type','res_id','src','lang'], context=context):
            self._get_source.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], source=trans_obj['src'])
            self._get_ids.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], [trans_obj['res_id']])
        return result

    def unlink(self, cursor, user, ids, context=None):
        if not context:
            context = {}
        if isinstance(ids, (int, long)):
            ids = [ids]
        for trans_obj in self.read(cursor, user, ids, ['name','type','res_id','src','lang'], context=context):
            self._get_source.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], source=trans_obj['src'])
            self._get_ids.clear_cache(cursor.dbname, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], [trans_obj['res_id']])
        result = super(ir_translation, self).unlink(cursor, user, ids, context=context)
        return result

ir_translation()

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

<|endoftext|>


<commit_before>import os
from django.db import models
from core.models import PlCoreBase
from core.models import Deployment,Controller,ControllerLinkManager,ControllerLinkDeletionManager

# Create your models here.

class Image(PlCoreBase):
    name = models.CharField(max_length=256, unique=True)
    disk_format = models.CharField(max_length=256)
    container_format = models.CharField(max_length=256)
    path = models.CharField(max_length=256, null=True, blank=True, help_text="Path to image on local disk")

    def __unicode__(self):  return u'%s' % (self.name)

class ImageDeployments(PlCoreBase):
    image = models.ForeignKey(Image,related_name='imagedeployments')
    deployment = models.ForeignKey(Deployment,related_name='imagedeployments')

    def __unicode__(self):  return u'%s %s' % (self.image, self.deployment)

class ControllerImages(PlCoreBase):
    objects = ControllerLinkManager()
    deleted_objects = ControllerLinkDeletionManager()
    image = models.ForeignKey(Image,related_name='controllerimages')
    controller = models.ForeignKey(Controller,related_name='controllerimages')
    glance_image_id = models.CharField(null=True, blank=True, max_length=200, help_text="Glance image id")

    def __unicode__(self):  return u'%s %s' % (self.image, self.controller)

<commit_msg>add ManyToMany for (Image, Deployment)<commit_after>import os
from django.db import models
from core.models import PlCoreBase
from core.models import Deployment,Controller,ControllerLinkManager,ControllerLinkDeletionManager

# Create your models here.

class Image(PlCoreBase):
    name = models.CharField(max_length=256, unique=True)
    disk_format = models.CharField(max_length=256)
    container_format = models.CharField(max_length=256)
    path = models.CharField(max_length=256, null=True, blank=True, help_text="Path to image on local disk")
    deployments = models.ManyToManyField('Deployment', through='ImageDeployments', blank=True, help_text="Select which images should be instantiated on this deployment", related_name='images')

    def __unicode__(self):  return u'%s' % (self.name)

class ImageDeployments(PlCoreBase):
    image = models.ForeignKey(Image,related_name='imagedeployments')
    deployment = models.ForeignKey(Deployment,related_name='imagedeployments')

    def __unicode__(self):  return u'%s %s' % (self.image, self.deployment)

class ControllerImages(PlCoreBase):
    objects = ControllerLinkManager()
    deleted_objects = ControllerLinkDeletionManager()
    image = models.ForeignKey(Image,related_name='controllerimages')
    controller = models.ForeignKey(Controller,related_name='controllerimages')
    glance_image_id = models.CharField(null=True, blank=True, max_length=200, help_text="Glance image id")

    def __unicode__(self):  return u'%s %s' % (self.image, self.controller)

<|endoftext|>