Ejemplo n.º 1
0
def url_for(path_or_uri, lang=None):
    current_path = request.httprequest.path     # should already be text
    location = pycompat.to_text(path_or_uri).strip()
    force_lang = lang is not None
    url = werkzeug.urls.url_parse(location)

    if not url.netloc and not url.scheme and (url.path or force_lang):
        location = werkzeug.urls.url_join(current_path, location)

        lang = pycompat.to_text(lang or request.context.get('lang') or 'en_US')
        langs = [lg[0] for lg in request.env['ir.http']._get_language_codes()]

        if (len(langs) > 1 or force_lang) and is_multilang_url(location, langs):
            ps = location.split(u'/')
            if ps[1] in langs:
                # Replace the language only if we explicitly provide a language to url_for
                if force_lang:
                    ps[1] = lang
                # Remove the default language unless it's explicitly provided
                elif ps[1] == request.env['ir.http']._get_default_lang().code:
                    ps.pop(1)
            # Insert the context language or the provided language
            elif lang != request.env['ir.http']._get_default_lang().code or force_lang:
                ps.insert(1, lang)
            location = u'/'.join(ps)

    return location
Ejemplo n.º 2
0
    def to_html(self,
                sep=None,
                css=True,
                js=True,
                debug=False,
                async_load=False,
                url_for=(lambda url: url),
                **kw):
        if 'async' in kw:
            _logger.warning(
                "Using deprecated argument 'async' in to_html call, use 'async_load' instead."
            )
            async_load = kw['async']
        nodes = self.to_node(css=css,
                             js=js,
                             debug=debug,
                             async_load=async_load)

        if sep is None:
            sep = u'\n            '
        response = []
        for tagName, attributes, content in nodes:
            html = u"<%s " % tagName
            for name, value in attributes.items():
                if value or isinstance(value, string_types):
                    html += u' %s="%s"' % (name, escape(to_text(value)))
            if content is None:
                html += u'/>'
            else:
                html += u'>%s</%s>' % (escape(to_text(content)), tagName)
            response.append(html)

        return sep + sep.join(response)
Ejemplo n.º 3
0
 def _compile_directive_snippet(self, el, options):
     el.set('t-call', el.attrib.pop('t-snippet'))
     name = self.env['ir.ui.view'].search([('key', '=', el.attrib.get('t-call'))]).display_name
     thumbnail = el.attrib.pop('t-thumbnail', "oe-thumbnail")
     div = u'<div name="%s" data-oe-type="snippet" data-oe-thumbnail="%s">' % (
         escape(pycompat.to_text(name)),
         escape(pycompat.to_text(thumbnail))
     )
     return [self._append(ast.Str(div))] + self._compile_node(el, options) + [self._append(ast.Str(u'</div>'))]
Ejemplo n.º 4
0
 def to_html(self):
     tagName, attributes, content = self.to_node()
     html = u"<%s " % tagName
     for name, value in attributes.items():
         if value or isinstance(value, string_types):
             html += u' %s="%s"' % (name, escape(to_text(value)))
     if content is None:
         html += u'/>'
     else:
         html += u'>%s</%s>' % (escape(to_text(content)), tagName)
     return html
Ejemplo n.º 5
0
    def record_to_html(self, record, field_name, options):
        assert options['tagName'] != 'img',\
            "Oddly enough, the root tag of an image field can not be img. " \
            "That is because the image goes into the tag, or it gets the " \
            "hose again."

        if options.get('qweb_img_raw_data', False):
            return super(Image, self).record_to_html(record, field_name,
                                                     options)

        aclasses = ['img', 'img-fluid'] if options.get('qweb_img_responsive',
                                                       True) else ['img']
        aclasses += options.get('class', '').split()
        classes = ' '.join(map(escape, aclasses))

        src, src_zoom = self._get_src_urls(record, field_name, options)

        if options.get('alt-field') and getattr(record, options['alt-field'],
                                                None):
            alt = escape(record[options['alt-field']])
        elif options.get('alt'):
            alt = options['alt']
        else:
            alt = escape(record.display_name)

        itemprop = None
        if options.get('itemprop'):
            itemprop = options['itemprop']

        atts = OrderedDict()
        atts["src"] = src
        atts["itemprop"] = itemprop
        atts["class"] = classes
        atts["style"] = options.get('style')
        atts["alt"] = alt
        atts["data-zoom"] = src_zoom and u'1' or None
        atts["data-zoom-image"] = src_zoom
        atts["data-no-post-process"] = options.get('data-no-post-process')

        atts = self.env['ir.qweb']._post_processing_att(
            'img', atts, options.get('template_options'))

        img = ['<img']
        for name, value in atts.items():
            if value:
                img.append(' ')
                img.append(escape(pycompat.to_text(name)))
                img.append('="')
                img.append(escape(pycompat.to_text(value)))
                img.append('"')
        img.append('/>')

        return u''.join(img)
Ejemplo n.º 6
0
 def to_node(self):
     if self.url:
         attr = OrderedDict([
             ["type", "text/css"],
             ["rel", "stylesheet"],
             ["href", self.html_url],
             ["media", escape(to_text(self.media)) if self.media else None]
         ])
         return ("link", attr, None)
     else:
         attr = OrderedDict([
             ["type", "text/css"],
             ["media", escape(to_text(self.media)) if self.media else None]
         ])
         return ("style", attr, self.with_header())
Ejemplo n.º 7
0
 def _compile_directive_install(self, el, options):
     if self.user_has_groups('base.group_system'):
         module = self.env['ir.module.module'].search([
             ('name', '=', el.attrib.get('t-install'))
         ])
         if not module or module.state == 'installed':
             return []
         name = el.attrib.get('string') or 'Snippet'
         thumbnail = el.attrib.pop('t-thumbnail', 'oe-thumbnail')
         div = u'<div name="%s" data-oe-type="snippet" data-module-id="%s" data-oe-thumbnail="%s"><section/></div>' % (
             escape(pycompat.to_text(name)), module.id,
             escape(pycompat.to_text(thumbnail)))
         return [self._append(ast.Str(div))]
     else:
         return []
Ejemplo n.º 8
0
 def content_common(self, xmlid=None, model='ir.attachment', id=None, field='datas', filename=None,
                    filename_field='datas_fname', mimetype=None, download=None, access_token=None):
     obj = None
     if xmlid:
         obj = request.env.ref(xmlid, False)
     elif id and model in request.env.registry:
         obj = request.env[model].browse(int(id))
     if not obj or not obj.exists() or field not in obj:
         return request.not_found()
     try:
         last_update = obj['__last_update']
     except AccessError:
         return wrappers.Response(status=403, headers=[])
     status, headers, content = None, [], None
     content = obj.with_context({'stream': True})[field] or b''
     if not filename:
         if filename_field in obj:
             filename = obj[filename_field]
         else:
             filename = "%s-%s-%s" % (obj._name, obj.id, field)
     mimetype = 'mimetype' in obj and obj.mimetype or False
     if not mimetype and filename:
         mimetype = mimetypes.guess_type(filename)[0]
     headers += [('Content-Type', mimetype), ('X-Content-Type-Options', 'nosniff')]
     etag = bool(request) and request.httprequest.headers.get('If-None-Match')
     retag = '"%s"' % hashlib.md5(pycompat.to_text(content).encode('utf-8')).hexdigest()
     status = status or (304 if etag == retag else 200)
     headers.append(('ETag', retag))
     if download:
         headers.append(('Content-Disposition', http.content_disposition(filename)))
     return wrappers.Response(content, headers=headers, direct_passthrough=True, status=status)
             
Ejemplo n.º 9
0
def iap_authorize(env,
                  key,
                  account_token,
                  credit,
                  dbuuid=False,
                  description=None,
                  credit_template=None,
                  ttl=4320):
    endpoint = iap_get_endpoint(env)
    params = {
        'account_token': account_token,
        'credit': credit,
        'key': key,
        'description': description,
        'ttl': ttl
    }
    if dbuuid:
        params.update({'dbuuid': dbuuid})
    try:
        transaction_token = iap_jsonrpc(endpoint + '/iap/1/authorize',
                                        params=params)
    except InsufficientCreditError as e:
        if credit_template:
            arguments = json.loads(e.args[0])
            arguments['body'] = pycompat.to_text(
                env['ir.qweb']._render(credit_template))
            e.args = (json.dumps(arguments), )
        raise e
    return transaction_token
Ejemplo n.º 10
0
    def value_to_html(self, value, options):
        if not value:
            return ''
        lang = self.user_lang()
        locale = babel.Locale.parse(lang.code)

        if isinstance(value, pycompat.string_types):
            value = fields.Datetime.from_string(value)

        value = fields.Datetime.context_timestamp(self, value)

        if options and 'format' in options:
            pattern = options['format']
        else:
            if options and options.get('time_only'):
                strftime_pattern = (u"%s" % (lang.time_format))
            else:
                strftime_pattern = (u"%s %s" % (lang.date_format, lang.time_format))

            pattern = posix_to_ldml(strftime_pattern, locale=locale)

        if options and options.get('hide_seconds'):
            pattern = pattern.replace(":ss", "").replace(":s", "")

        return pycompat.to_text(babel.dates.format_datetime(value, format=pattern, locale=locale))
Ejemplo n.º 11
0
    def value_to_html(self, value, options):
        """ value_to_html(value, field, options=None)

        Converts a single value to its HTML version/output
        :rtype: unicode
        """
        return html_escape(pycompat.to_text(value), options)
Ejemplo n.º 12
0
    def _authenticate(self, conf, login, password):
        """
        Authenticate a user against the specified LDAP server.

        In order to prevent an unintended 'unauthenticated authentication',
        which is an anonymous bind with a valid dn and a blank password,
        check for empty passwords explicitely (:rfc:`4513#section-6.3.1`)
        :param dict conf: LDAP configuration
        :param login: username
        :param password: Password for the LDAP user
        :return: LDAP entry of authenticated user or False
        :rtype: dictionary of attributes
        """

        if not password:
            return False

        dn, entry = self._get_entry(conf, login)
        if not dn:
            return False
        try:
            conn = self._connect(conf)
            conn.simple_bind_s(dn, to_text(password))
            conn.unbind()
        except ldap.INVALID_CREDENTIALS:
            return False
        except ldap.LDAPError as e:
            _logger.error('An LDAP exception occurred: %s', e)
        return entry
Ejemplo n.º 13
0
    def attributes(self, record, field_name, options, values):
        attrs = super(Date, self).attributes(record, field_name, options,
                                             values)
        attrs['data-oe-original'] = record[field_name]

        if record._fields[field_name].type == 'datetime':
            attrs = self.env['ir.qweb.field.datetime'].attributes(
                record, field_name, options, values)
            attrs['data-oe-type'] = 'datetime'
            return attrs

        lg = self.env['res.lang']._lang_get(self.env.user.lang)
        locale = babel.Locale.parse(lg.code)
        babel_format = value_format = posix_to_ldml(lg.date_format,
                                                    locale=locale)

        if record[field_name]:
            date = fields.Date.from_string(record[field_name])
            value_format = pycompat.to_text(
                babel.dates.format_date(date,
                                        format=babel_format,
                                        locale=locale))

        attrs['data-oe-original-with-format'] = value_format
        return attrs
Ejemplo n.º 14
0
    def attributes(self, record, field_name, options, values):
        attrs = super(DateTime, self).attributes(record, field_name, options,
                                                 values)
        value = record[field_name]

        lg = self.env['res.lang']._lang_get(self.env.user.lang)
        locale = babel.Locale.parse(lg.code)
        babel_format = value_format = posix_to_ldml(
            '%s %s' % (lg.date_format, lg.time_format), locale=locale)
        tz = record.env.context.get('tz') or self.env.user.tz

        if isinstance(value, pycompat.string_types):
            value = fields.Datetime.from_string(value)

        if value:
            # convert from UTC (server timezone) to user timezone
            value = fields.Datetime.context_timestamp(self.with_context(tz=tz),
                                                      timestamp=value)
            value_format = pycompat.to_text(
                babel.dates.format_datetime(value,
                                            format=babel_format,
                                            locale=locale))
            value = fields.Datetime.to_string(value)

        attrs['data-oe-original'] = value
        attrs['data-oe-original-with-format'] = value_format
        attrs['data-oe-original-tz'] = tz
        return attrs
Ejemplo n.º 15
0
def charge(env,
           key,
           account_token,
           credit,
           description=None,
           credit_template=None,
           dbuuid=False):
    """
    Account charge context manager: takes a hold for ``credit``
    amount before executing the body, then captures it if there
    is no error, or cancels it if the body generates an exception.

    :param str key: service identifier
    :param str account_token: user identifier
    :param int credit: cost of the body's operation
    :param description: a description of the purpose of the charge,
                        the user will be able to see it in their
                        dashboard
    :type description: str
    :param credit_template: a QWeb template to render and show to the
                            user if their account does not have enough
                            credits for the requested operation
    :type credit_template: str
    """
    endpoint = get_endpoint(env)
    params = {
        'account_token': account_token,
        'credit': credit,
        'key': key,
        'description': description,
        'dbuuid': dbuuid,
    }
    try:
        transaction_token = jsonrpc(endpoint + '/iap/1/authorize',
                                    params=params)
    except InsufficientCreditError as e:
        if credit_template:
            arguments = json.loads(e.args[0])
            arguments['body'] = pycompat.to_text(
                env['ir.qweb'].render(credit_template))
            e.args = (json.dumps(arguments), )
        raise e
    try:
        transaction = IapTransaction()
        transaction.credit = credit
        yield transaction
    except Exception as e:
        params = {
            'token': transaction_token,
            'key': key,
        }
        r = jsonrpc(endpoint + '/iap/1/cancel', params=params)
        raise e
    else:
        params = {
            'token': transaction_token,
            'key': key,
            'credit_to_capture': transaction.credit,
        }
        r = jsonrpc(endpoint + '/iap/1/capture', params=params)  # noqa
Ejemplo n.º 16
0
    def value_to_html(self, value, options):
        if 'decimal_precision' in options:
            precision = self.env['decimal.precision'].search([
                ('name', '=', options['decimal_precision'])
            ]).digits
        else:
            precision = options['precision']

        if precision is None:
            fmt = '%f'
        else:
            value = float_utils.float_round(value, precision_digits=precision)
            fmt = '%.{precision}f'.format(precision=precision)

        formatted = self.user_lang().format(fmt, value, grouping=True).replace(
            r'-', u'-\N{ZERO WIDTH NO-BREAK SPACE}')

        # %f does not strip trailing zeroes. %g does but its precision causes
        # it to switch to scientific notation starting at a million *and* to
        # strip decimals. So use %f and if no precision was specified manually
        # strip trailing 0.
        if precision is None:
            formatted = re.sub(r'(?:(0|\d+?)0+)$', r'\1', formatted)

        return pycompat.to_text(formatted)
Ejemplo n.º 17
0
def nl2br(string):
    """ Converts newlines to HTML linebreaks in ``string``. returns
    the unicode result

    :param str string:
    :rtype: unicode
    """
    return pycompat.to_text(string).replace(u'\n', u'<br>\n')
Ejemplo n.º 18
0
 def fiscal_pos_map_to_csv(self):
     writer = pycompat.csv_writer(open('account.fiscal.'
                                  'position.tax.template-%s.csv' %
                                  self.suffix, 'wb'))
     fiscal_pos_map_iterator = self.iter_fiscal_pos_map()
     keys = next(fiscal_pos_map_iterator)
     writer.writerow(keys)
     for row in fiscal_pos_map_iterator:
         writer.writerow([pycompat.to_text(s) for s in row.values()])
Ejemplo n.º 19
0
    def value_to_html(self, value, options):
        locale = babel.Locale.parse(self.user_lang().code)

        if isinstance(value, pycompat.string_types):
            value = fields.Datetime.from_string(value)

        # value should be a naive datetime in UTC. So is fields.Datetime.now()
        reference = fields.Datetime.from_string(options['now'])

        return pycompat.to_text(babel.dates.format_timedelta(value - reference, add_direction=True, locale=locale))
Ejemplo n.º 20
0
 def to_node(self):
     if self.url:
         attr = OrderedDict([
             ["type", "text/css"],
             ["rel", "stylesheet"],
             ["href", self.html_url],
             ["media", escape(to_text(self.media)) if self.media else None],
             ['data-asset-xmlid', self.bundle.name],
             ['data-asset-version', self.bundle.version],
         ])
         return ("link", attr, None)
     else:
         attr = OrderedDict([
             ["type", "text/css"],
             ["media", escape(to_text(self.media)) if self.media else None],
             ['data-asset-xmlid', self.bundle.name],
             ['data-asset-version', self.bundle.version],
         ])
         return ("style", attr, self.with_header())
Ejemplo n.º 21
0
    def record_to_html(self, record, field_name, options):
        if not getattr(record, field_name):
            return None

        view = getattr(record, field_name)

        if view._name != "ir.ui.view":
            _logger.warning("%s.%s must be a 'ir.ui.view' model." % (record, field_name))
            return None

        return pycompat.to_text(view._render(options.get('values', {}), engine='ir.qweb'))
Ejemplo n.º 22
0
    def value_to_html(self, value, options):
        if not value:
            return ''
        options = options or {}

        lang = self.user_lang()
        locale = babel_locale_parse(lang.code)
        format_func = babel.dates.format_datetime
        if isinstance(value, str):
            value = fields.Datetime.from_string(value)

        value = fields.Datetime.context_timestamp(self, value)

        if options.get('tz_name'):
            tzinfo = babel.dates.get_timezone(options['tz_name'])
        else:
            tzinfo = None

        if 'format' in options:
            pattern = options['format']
        else:
            if options.get('time_only'):
                strftime_pattern = (u"%s" % (lang.time_format))
            elif options.get('date_only'):
                strftime_pattern = (u"%s" % (lang.date_format))
            else:
                strftime_pattern = (u"%s %s" % (lang.date_format, lang.time_format))

            pattern = posix_to_ldml(strftime_pattern, locale=locale)

        if options.get('hide_seconds'):
            pattern = pattern.replace(":ss", "").replace(":s", "")

        if options.get('time_only'):
            format_func = babel.dates.format_time
            return pycompat.to_text(format_func(value, format=pattern, locale=locale))
        if options.get('date_only'):
            format_func = babel.dates.format_date
            return pycompat.to_text(format_func(value, format=pattern, locale=locale))

        return pycompat.to_text(format_func(value, format=pattern, tzinfo=tzinfo, locale=locale))
Ejemplo n.º 23
0
    def _query(self, conf, filter, retrieve_attributes=None):
        """
        Query an LDAP server with the filter argument and scope subtree.

        Allow for all authentication methods of the simple authentication
        method:

        - authenticated bind (non-empty binddn + valid password)
        - anonymous bind (empty binddn + empty password)
        - unauthenticated authentication (non-empty binddn + empty password)

        .. seealso::
           :rfc:`4513#section-5.1` - LDAP: Simple Authentication Method.

        :param dict conf: LDAP configuration
        :param filter: valid LDAP filter
        :param list retrieve_attributes: LDAP attributes to be retrieved. \
        If not specified, return all attributes.
        :return: ldap entries
        :rtype: list of tuples (dn, attrs)

        """

        results = []
        try:
            conn = self._connect(conf)
            ldap_password = conf['ldap_password'] or ''
            ldap_binddn = conf['ldap_binddn'] or ''
            conn.simple_bind_s(to_text(ldap_binddn), to_text(ldap_password))
            results = conn.search_st(to_text(conf['ldap_base']),
                                     ldap.SCOPE_SUBTREE,
                                     filter,
                                     retrieve_attributes,
                                     timeout=60)
            conn.unbind()
        except ldap.INVALID_CREDENTIALS:
            _logger.error('LDAP bind failed.')
        except ldap.LDAPError as e:
            _logger.error('An LDAP exception occurred: %s', e)
        return results
Ejemplo n.º 24
0
    def record_to_html(self, record, field_name, options):
        if not getattr(record, field_name):
            return None

        view = getattr(record, field_name)

        if view._name != "ir.ui.view":
            _logger.warning("%s.%s must be a 'ir.ui.view' model." % (record, field_name))
            return None

        view = view.with_context(object=record)

        return pycompat.to_text(view.render(view._context, engine='ir.qweb'))
Ejemplo n.º 25
0
def url_lang(path_or_uri, lang_code=None):
    ''' Given a relative URL, make it absolute and add the required lang or
        remove useless lang.
        Nothing will be done for absolute URL.
        If there is only one language installed, the lang will not be handled
        unless forced with `lang` parameter.

        :param lang_code: Must be the lang `code`. It could also be something
                          else, such as `'[lang]'` (used for url_return).
    '''
    Lang = request.env['res.lang']
    location = pycompat.to_text(path_or_uri).strip()
    force_lang = lang_code is not None
    url = werkzeug.urls.url_parse(location)
    # relative URL with either a path or a force_lang
    if not url.netloc and not url.scheme and (url.path or force_lang):
        location = werkzeug.urls.url_join(request.httprequest.path, location)
        lang_url_codes = [url_code for _, url_code, *_ in Lang.get_available()]
        lang_code = pycompat.to_text(lang_code or request.context['lang'])
        lang_url_code = Lang._lang_code_to_urlcode(lang_code)
        lang_url_code = lang_url_code if lang_url_code in lang_url_codes else lang_code

        if (len(lang_url_codes) > 1 or force_lang) and is_multilang_url(
                location, lang_url_codes):
            ps = location.split(u'/')
            default_lg = request.env['ir.http']._get_default_lang()
            if ps[1] in lang_url_codes:
                # Replace the language only if we explicitly provide a language to url_for
                if force_lang:
                    ps[1] = lang_url_code
                # Remove the default language unless it's explicitly provided
                elif ps[1] == default_lg.url_code:
                    ps.pop(1)
            # Insert the context language or the provided language
            elif lang_url_code != default_lg.url_code or force_lang:
                ps.insert(1, lang_url_code)
            location = u'/'.join(ps)
    return location
Ejemplo n.º 26
0
    def _adyen_form_get_tx_from_data(self, data):
        reference, pspReference = data.get('merchantReference'), data.get(
            'pspReference')
        if not reference or not pspReference:
            error_msg = _(
                'Adyen: received data with missing reference (%s) or missing pspReference (%s)'
            ) % (reference, pspReference)
            _logger.info(error_msg)
            raise ValidationError(error_msg)

        # find tx -> @TDENOTE use pspReference ?
        tx = self.env['payment.transaction'].search([('reference', '=',
                                                      reference)])
        if not tx or len(tx) > 1:
            error_msg = _('Adyen: received data for reference %s') % (
                reference)
            if not tx:
                error_msg += _('; no order found')
            else:
                error_msg += _('; multiple order found')
            _logger.info(error_msg)
            raise ValidationError(error_msg)

        # verify shasign
        if len(tx.acquirer_id.adyen_skin_hmac_key) == 64:
            shasign_check = tx.acquirer_id._adyen_generate_merchant_sig_sha256(
                'out', data)
        else:
            shasign_check = tx.acquirer_id._adyen_generate_merchant_sig(
                'out', data)
        if to_text(shasign_check) != to_text(data.get('merchantSig')):
            error_msg = _(
                'Adyen: invalid merchantSig, received %s, computed %s') % (
                    data.get('merchantSig'), shasign_check)
            _logger.warning(error_msg)
            raise ValidationError(error_msg)

        return tx
Ejemplo n.º 27
0
    def encode_addr(addr):
        name, email = addr
        # If s is a <text string>, then charset is a hint specifying the
        # character set of the characters in the string. The Unicode string
        # will be encoded using the following charsets in order: us-ascii,
        # the charset hint, utf-8. The first character set to not provoke a
        # UnicodeError is used.
        # -> always pass a text string to Header

        # also Header.__str__ in Python 3 "Returns an approximation of the
        # Header as a string, using an unlimited line length.", the old one
        # was "A synonym for Header.encode()." so call encode() directly?
        name = Header(pycompat.to_text(name)).encode()
        return formataddr((name, email))
Ejemplo n.º 28
0
 def _change_password(self, conf, login, old_passwd, new_passwd):
     changed = False
     dn, entry = self._get_entry(conf, login)
     if not dn:
         return False
     try:
         conn = self._connect(conf)
         conn.simple_bind_s(dn, to_text(old_passwd))
         conn.passwd_s(dn, old_passwd, new_passwd)
         changed = True
         conn.unbind()
     except ldap.INVALID_CREDENTIALS:
         pass
     except ldap.LDAPError as e:
         _logger.error('An LDAP exception occurred: %s', e)
     return changed
Ejemplo n.º 29
0
    def record_to_html(self, record, field_name, options):
        assert options['tagName'] != 'img',\
            "Oddly enough, the root tag of an image field can not be img. " \
            "That is because the image goes into the tag, or it gets the " \
            "hose again."

        if options.get('qweb_img_raw_data', False):
            return super(Image, self).record_to_html(record, field_name,
                                                     options)

        aclasses = ['img', 'img-responsive'] if options.get(
            'qweb_img_responsive', True) else ['img']
        aclasses += options.get('class', '').split()
        classes = ' '.join(pycompat.imap(escape, aclasses))

        max_size = None
        if options.get('resize'):
            max_size = options.get('resize')
        else:
            max_width, max_height = options.get('max_width', 0), options.get(
                'max_height', 0)
            if max_width or max_height:
                max_size = '%sx%s' % (max_width, max_height)

        sha = hashlib.sha1(getattr(
            record, '__last_update').encode('utf-8')).hexdigest()[0:7]
        max_size = '' if max_size is None else '/%s' % max_size
        src = '/web/image/%s/%s/%s%s?unique=%s' % (record._name, record.id,
                                                   field_name, max_size, sha)

        alt = None
        if options.get('alt-field') and getattr(record, options['alt-field'],
                                                None):
            alt = escape(record[options['alt-field']])
        elif options.get('alt'):
            alt = options['alt']

        src_zoom = None
        if options.get('zoom') and getattr(record, options['zoom'], None):
            src_zoom = '/web/image/%s/%s/%s%s?unique=%s' % (
                record._name, record.id, options['zoom'], max_size, sha)
        elif options.get('zoom'):
            src_zoom = options['zoom']

        img = '<img class="%s" src="%s" style="%s"%s%s/>' % \
            (classes, src, options.get('style', ''), ' alt="%s"' % alt if alt else '', ' data-zoom="1" data-zoom-image="%s"' % src_zoom if src_zoom else '')
        return pycompat.to_text(img)
Ejemplo n.º 30
0
 def taxes_to_csv(self):
     writer = pycompat.csv_writer(
         open('account.tax.template-%s.csv' % self.suffix, 'wb'))
     taxes_iterator = self.iter_taxes()
     keys = next(taxes_iterator)
     writer.writerow(keys[3:] + ['sequence'])
     seq = 100
     for row in sorted(taxes_iterator, key=lambda r: r['description']):
         if not _is_true(row['active']):
             continue
         seq += 1
         if row['parent_id:id']:
             cur_seq = seq + 1000
         else:
             cur_seq = seq
         writer.writerow(
             [pycompat.to_text(v)
              for v in list(row.values())[3:]] + [cur_seq])