Example #1
0
class GettextTag:
    """ """

    name = 'gettext'
    blockContinuations = ()

    def __init__(self, blocks):
        tname, args, section = blocks[0]
        self.section = section.blocks

        args = parse_params(args,
                            lang=None,
                            lang_expr=None,
                            verbatim=1,
                            catalog=None,
                            data=None)

        self.lang = name_or_expr(args, 'lang', 'lang_expr', None)

        self.verbatim = args.get('', None) == 'verbatim' \
                        or args.get('verbatim', None)

        self.catalog = args.get('catalog', None)

        self.data = args.get('data', None)
        if self.data is not None:
            self.data = Eval(self.data)

    def __call__(self, md):
        # In which language, if any?
        lang = self.lang
        if lang is not None and type(lang) is not str:
            lang = lang.eval(md)

        # Get the message!!
        ns = namespace(md)[0]
        md._push(InstanceDict(ns, md))
        message = render_blocks(self.section, md)
        md._pop(1)

        # Interpret the message as verbatim or not
        if not self.verbatim:
            message = ' '.join([x.strip() for x in message.split()])

        # Search in a specific catalog
        if self.catalog is None:
            gettext = md.getitem('gettext', 0)
        else:
            gettext = md.getitem(self.catalog, 0).gettext

        translation = gettext(message, lang)

        # Variable substitution
        if self.data is not None:
            data = self.data.eval(md)
            translation = translation % data

        return translation
Example #2
0
class GettextTag:
    """ """

    name = 'gettext'
    blockContinuations = ()

    def __init__(self, blocks):
        tname, args, section = blocks[0]
        self.section = section.blocks

        args = parse_params(args, lang=None, lang_expr=None, verbatim=1,
                            catalog=None, data=None)

        self.lang = name_or_expr(args, 'lang', 'lang_expr', None)

        self.verbatim = args.get('', None) == 'verbatim' \
                        or args.get('verbatim', None)

        self.catalog = args.get('catalog', None)

        self.data = args.get('data', None)
        if self.data is not None:
            self.data = Eval(self.data)


    def __call__(self, md):
        # In which language, if any?
        lang = self.lang
        if lang is not None and type(lang) is not str:
            lang = lang.eval(md)

        # Get the message!!
        ns = namespace(md)[0]
        md._push(InstanceDict(ns, md))
        message = render_blocks(self.section, md)
        md._pop(1)

        # Interpret the message as verbatim or not
        if not self.verbatim:
            message = ' '.join([ x.strip() for x in message.split() ])

        # Search in a specific catalog
        if self.catalog is None:
            gettext = md.getitem('gettext', 0)
        else:
            gettext = md.getitem(self.catalog, 0).gettext

        translation = gettext(message, lang)

        # Variable substitution
        if self.data is not None:
            data = self.data.eval(md)
            translation = translation % data

        return translation
Example #3
0
 def __call__(self, md):
     # md is a TemplateDict instance.
     eval = self._v_eval
     if eval is None:
         text = self.text
         if expr_globals is not None:
             eval = Eval(text, expr_globals)
         else:
             eval = Eval(text)
         self._v_eval = eval
     md.validate = self.validate  # Zope 2.3.x
     md.read_guard = self.read_guard  # Zope 2.4.x
     return eval.eval(md)
Example #4
0
class InClass(object):
    elses = None
    expr = sort = batch = mapping = no_push_item = None
    start_name_re = None
    reverse = None
    sort_expr = reverse_expr = None

    def __init__(self, blocks):
        tname, args, section = blocks[0]
        args = parse_params(args,
                            name='',
                            start='1',
                            end='-1',
                            size='10',
                            orphan='0',
                            overlap='1',
                            mapping=1,
                            no_push_item=1,
                            skip_unauthorized=1,
                            previous=1,
                            next=1,
                            expr='',
                            sort='',
                            reverse=1,
                            sort_expr='',
                            reverse_expr='',
                            prefix='')
        self.args = args

        if 'sort' in args:
            self.sort = sort = args['sort']
            if sort == 'sequence-item':
                self.sort = ''

        if 'sort_expr' in args:
            self.sort_expr = Eval(args['sort_expr'])

        if 'reverse_expr' in args:
            self.reverse_expr = Eval(args['reverse_expr'])

        if 'reverse' in args:
            self.reverse = args['reverse']

        if 'no_push_item' in args:
            self.no_push_item = args['no_push_item']

        if 'mapping' in args:
            self.mapping = args['mapping']
        for n in 'start', 'size', 'end':
            if n in args:
                self.batch = 1

        prefix = args.get('prefix')
        if prefix and not simple_name(prefix):
            raise ParseError('prefix is not a simple name', 'in')

        for n in ('orphan', 'overlap', 'previous', 'next'):
            if n in args and not self.batch:
                raise ParseError(
                    """
                    The %s attribute was used but neither of the
                    <code>start</code>, <code>end</code>, or <code>size</code>
                    attributes were used.
                    """ % n, 'in')

        if 'start' in args:
            v = args['start']
            if isinstance(v, str):
                try:
                    int(v)
                except Exception:
                    self.start_name_re = re.compile(
                        '&+' + ''.join(["[%s]" % c for c in v]) + '=[0-9]+&+')

        name, expr = name_param(args, 'in', 1)
        if expr is not None:
            expr = expr.eval
        self.__name__, self.expr = name, expr
        self.section = section.blocks
        if len(blocks) > 1:
            if len(blocks) != 2:
                raise ParseError('too many else blocks', 'in')
            tname, args, section = blocks[1]
            args = parse_params(args, name='')
            if args:
                ename = name_param(args)
                if ename != name:
                    raise ParseError('name in else does not match in', 'in')
            self.elses = section.blocks

    def renderwb(self, md):
        expr = self.expr
        name = self.__name__
        if expr is None:
            sequence = md[name]
            cache = {name: sequence}
        else:
            sequence = expr(md)
            cache = None

        if not sequence:
            if self.elses:
                return render_blocks(self.elses, md)
            return ''

        if isinstance(sequence, str):
            raise ValueError('Strings are not allowed as input to the in tag.')

        # Turn iterable like dict.keys() into a list.
        sequence = list(sequence)
        if cache is not None:
            cache[name] = sequence

        section = self.section
        params = self.args

        mapping = self.mapping
        no_push_item = self.no_push_item

        if self.sort_expr is not None:
            self.sort = self.sort_expr.eval(md)
            sequence = self.sort_sequence(sequence, md)
        elif self.sort is not None:
            sequence = self.sort_sequence(sequence, md)

        if self.reverse_expr is not None and self.reverse_expr.eval(md):
            sequence = self.reverse_sequence(sequence)
        elif self.reverse is not None:
            sequence = self.reverse_sequence(sequence)

        next = previous = 0
        try:
            start = int_param(params, md, 'start', 0)
        except Exception:
            start = 1
        end = int_param(params, md, 'end', 0)
        size = int_param(params, md, 'size', 0)
        overlap = int_param(params, md, 'overlap', 0)
        orphan = int_param(params, md, 'orphan', '0')
        start, end, sz = opt(start, end, size, orphan, sequence)
        if 'next' in params:
            next = 1
        if 'previous' in params:
            previous = 1

        last = end - 1
        first = start - 1

        try:
            query_string = md['QUERY_STRING']
        except Exception:
            query_string = ''
        prefix = params.get('prefix')
        vars = sequence_variables(sequence, '?' + query_string,
                                  self.start_name_re, prefix)
        kw = vars.data
        pkw = add_with_prefix(kw, 'sequence', prefix)
        for k, v in list(kw.items()):
            pkw[k] = v
        pkw['sequence-step-size'] = sz
        pkw['sequence-step-overlap'] = overlap
        pkw['sequence-step-start'] = start
        pkw['sequence-step-end'] = end
        pkw['sequence-step-start-index'] = start - 1
        pkw['sequence-step-end-index'] = end - 1
        pkw['sequence-step-orphan'] = orphan

        kw['mapping'] = mapping

        push = md._push
        pop = md._pop
        render = render_blocks

        if cache:
            push(cache)
        push(vars)
        try:
            if previous:
                if first > 0:
                    pstart, pend, psize = opt(0, first + overlap, sz, orphan,
                                              sequence)
                    pkw['previous-sequence'] = 1
                    pkw['previous-sequence-start-index'] = pstart - 1
                    pkw['previous-sequence-end-index'] = pend - 1
                    pkw['previous-sequence-size'] = pend + 1 - pstart
                    result = render(section, md)

                elif self.elses:
                    result = render(self.elses, md)
                else:
                    result = ''
            elif next:
                try:
                    # The following line is a sneaky way to test whether
                    # there are more items, without actually
                    # computing a length:
                    sequence[end]
                except IndexError:
                    if self.elses:
                        result = render(self.elses, md)
                    else:
                        result = ''
                else:
                    pstart, pend, psize = opt(end + 1 - overlap, 0, sz, orphan,
                                              sequence)
                    pkw['next-sequence'] = 1
                    pkw['next-sequence-start-index'] = pstart - 1
                    pkw['next-sequence-end-index'] = pend - 1
                    pkw['next-sequence-size'] = pend + 1 - pstart
                    result = render(section, md)
            else:
                result = []
                append = result.append
                guarded_getitem = getattr(md, 'guarded_getitem', None)
                for index in range(first, end):
                    # preset
                    pkw['previous-sequence'] = 0
                    # now more often defined then previously
                    pkw['next-sequence'] = 0
                    #
                    if index == first or index == last:
                        # provide batching information
                        if first > 0:
                            pstart, pend, psize = opt(0, first + overlap, sz,
                                                      orphan, sequence)
                            if index == first:
                                pkw['previous-sequence'] = 1
                            pkw['previous-sequence-start-index'] = pstart - 1
                            pkw['previous-sequence-end-index'] = pend - 1
                            pkw['previous-sequence-size'] = pend + 1 - pstart
                        try:
                            # The following line is a sneaky way to
                            # test whether there are more items,
                            # without actually computing a length:
                            sequence[end]
                            pstart, pend, psize = opt(end + 1 - overlap, 0, sz,
                                                      orphan, sequence)
                            if index == last:
                                pkw['next-sequence'] = 1
                            pkw['next-sequence-start-index'] = pstart - 1
                            pkw['next-sequence-end-index'] = pend - 1
                            pkw['next-sequence-size'] = pend + 1 - pstart
                        except Exception:
                            pass

                    if index == last:
                        pkw['sequence-end'] = 1

                    if guarded_getitem is not None:
                        try:
                            client = guarded_getitem(sequence, index)
                        except ValidationError as vv:
                            if ('skip_unauthorized' in params
                                    and params['skip_unauthorized']):
                                if index == first:
                                    pkw['sequence-start'] = 0
                                continue
                            raise ValidationError(
                                '(item %s): %s' % (index, vv),
                                sys.exc_info()[2])
                    else:
                        client = sequence[index]

                    pkw['sequence-index'] = index
                    t = type(client)
                    if t is TupleType and len(client) == 2:
                        client = client[1]

                    if no_push_item:
                        pushed = 0
                    elif mapping:
                        pushed = 1
                        push(client)
                    elif t in StringTypes:
                        pushed = 0
                    else:
                        pushed = 1
                        push(InstanceDict(client, md))

                    try:
                        append(render(section, md))
                    finally:
                        if pushed:
                            pop()

                    if index == first:
                        pkw['sequence-start'] = 0

                result = join_unicode(result)

        finally:
            if cache:
                pop()
            pop()

        return result

    def renderwob(self, md):
        """RENDER WithOutBatch"""
        expr = self.expr
        name = self.__name__
        if expr is None:
            sequence = md[name]
            cache = {name: sequence}
        else:
            sequence = expr(md)
            cache = None

        if not sequence:
            if self.elses:
                return render_blocks(self.elses, md)
            return ''

        if isinstance(sequence, str):
            raise ValueError('Strings are not allowed as input to the in tag.')

        # Turn iterable like dict.keys() into a list.
        sequence = list(sequence)
        if cache is not None:
            cache[name] = sequence

        section = self.section
        mapping = self.mapping
        no_push_item = self.no_push_item

        if self.sort_expr is not None:
            self.sort = self.sort_expr.eval(md)
            sequence = self.sort_sequence(sequence, md)
        elif self.sort is not None:
            sequence = self.sort_sequence(sequence, md)

        if self.reverse_expr is not None and self.reverse_expr.eval(md):
            sequence = self.reverse_sequence(sequence)
        elif self.reverse is not None:
            sequence = self.reverse_sequence(sequence)

        prefix = self.args.get('prefix')
        vars = sequence_variables(sequence, alt_prefix=prefix)
        kw = vars.data
        pkw = add_with_prefix(kw, 'sequence', prefix)
        for k, v in list(kw.items()):
            pkw[k] = v
        kw['mapping'] = mapping

        l_ = len(sequence)
        last = l_ - 1

        push = md._push
        pop = md._pop
        render = render_blocks

        if cache:
            push(cache)
        push(vars)
        try:
            result = []
            append = result.append
            guarded_getitem = getattr(md, 'guarded_getitem', None)
            for index in range(l_):
                if index == last:
                    pkw['sequence-end'] = 1
                if guarded_getitem is not None:
                    try:
                        client = guarded_getitem(sequence, index)
                    except ValidationError as vv:
                        if ('skip_unauthorized' in self.args
                                and self.args['skip_unauthorized']):
                            if index == 1:
                                pkw['sequence-start'] = 0
                            continue
                        raise ValidationError('(item %s): %s' % (index, vv),
                                              sys.exc_info()[2])
                else:
                    client = sequence[index]

                pkw['sequence-index'] = index
                t = type(client)
                if t is TupleType and len(client) == 2:
                    client = client[1]

                if no_push_item:
                    pushed = 0
                elif mapping:
                    pushed = 1
                    push(client)
                elif t in StringTypes:
                    pushed = 0
                else:
                    pushed = 1
                    push(InstanceDict(client, md))

                try:
                    append(render(section, md))
                finally:
                    if pushed:
                        pop()
                if index == 0:
                    pkw['sequence-start'] = 0

            result = join_unicode(result)

        finally:
            if cache:
                pop()
            pop()

        return result

    def sort_sequence(self, sequence, md):

        # Modified with multiple sort fields by Ross Lazarus
        # April 7 2000 [email protected]
        # eg <dtml-in "foo" sort="akey,anotherkey">

        # Modified with advanced sort functions by
        # Oleg Broytmann <*****@*****.**> 30 Mar 2001
        # eg <dtml-in "foo" sort="akey/nocase,anotherkey/cmp/desc">

        sort = self.sort
        need_sortfunc = sort.find('/') >= 0

        sortfields = sort.split(',')  # multi sort = key1,key2
        multsort = len(sortfields) > 1  # flag: is multiple sort

        if need_sortfunc:
            # prepare the list of functions and sort order multipliers
            sf_list = make_sortfunctions(sortfields, md)

            # clean the mess a bit
            if multsort:  # More than one sort key.
                sortfields = tuple(map(lambda x: x[0], sf_list))
            else:
                sort = sf_list[0][0]

        mapping = self.mapping
        isort = not sort

        s = []
        for client in sequence:
            k = None
            if type(client) == TupleType and len(client) == 2:
                if isort:
                    k = client[0]
                v = client[1]
            else:
                if isort:
                    k = client
                v = client

            if sort:
                if multsort:  # More than one sort key.
                    k = []
                    for sk in sortfields:
                        if mapping:
                            akey = v.get(sk)
                        else:
                            akey = getattr(v, sk, None)
                        if not basic_type(akey):
                            try:
                                akey = akey()
                            except Exception:
                                pass
                        k.append(akey)
                else:  # One sort key.
                    if mapping:
                        k = v.get(sort)
                    else:
                        k = getattr(v, sort, None)
                    if not basic_type(type(k)):
                        try:
                            k = k()
                        except Exception:
                            k = _Smallest

            s.append((k, client))

        if need_sortfunc:
            by = SortBy(multsort, sf_list)
            s.sort(key=functools.cmp_to_key(by))
        else:
            # In python 3 a key is required when tuples in the list have
            # the same sort key to prevent attempting to compare the second
            # item which is dict.
            s.sort(key=itemgetter(0))

        sequence = []
        for k, client in s:
            sequence.append(client)
        return sequence

    def reverse_sequence(self, sequence):
        s = list(sequence)
        s.reverse()
        return s
Example #5
0
class InClass:
    elses=None
    expr=sort=batch=mapping=no_push_item=None
    start_name_re=None
    reverse=None
    sort_expr=reverse_expr=None

    def __init__(self, blocks):
        tname, args, section = blocks[0]
        args=parse_params(args, name='', start='1',end='-1',size='10',
                          orphan='0',overlap='1',mapping=1,
                          no_push_item=1,
                          skip_unauthorized=1,
                          previous=1, next=1, expr='', sort='',
                          reverse=1, sort_expr='', reverse_expr='',
                          prefix='')
        self.args=args
        has_key=args.has_key

        if has_key('sort'):
            self.sort=sort=args['sort']
            if sort=='sequence-item': self.sort=''

        if has_key('sort_expr'):
            self.sort_expr=Eval(args['sort_expr'])

        if has_key('reverse_expr'):
            self.reverse_expr=Eval(args['reverse_expr'])

        if has_key('reverse'):
            self.reverse=args['reverse']

        if has_key('no_push_item'):
            self.no_push_item=args['no_push_item']

        if has_key('mapping'): self.mapping=args['mapping']
        for n in 'start', 'size', 'end':
            if has_key(n): self.batch=1

        prefix = args.get('prefix')
        if prefix and not simple_name(prefix):
            raise ParseError, _tm(
                'prefix is not a simple name', 'in')

        for n in 'orphan','overlap','previous','next':
            if has_key(n) and not self.batch:
                raise ParseError, (
                    """
                    The %s attribute was used but neither of the
                    <code>start</code>, <code>end</code>, or <code>size</code>
                    attributes were used.
                    """ % n, 'in')

        if has_key('start'):
            v=args['start']
            if type(v)==type(''):
                try: int(v)
                except:

                    self.start_name_re=re.compile(
                        '&+'+
                        ''.join(["[%s]" % c for c in v])+
                        '=[0-9]+&+')

        name,expr=name_param(args,'in',1)
        if expr is not None: expr=expr.eval
        self.__name__, self.expr = name, expr
        self.section=section.blocks
        if len(blocks) > 1:
            if len(blocks) != 2: raise ParseError, (
                'too many else blocks', 'in')
            tname, args, section = blocks[1]
            args=parse_params(args, name='')
            if args:
                ename=name_param(args)
                if ename != name:
                    raise ParseError, (
                        'name in else does not match in', 'in')
            self.elses=section.blocks


    def renderwb(self, md):
        expr=self.expr
        name=self.__name__
        if expr is None:
            sequence=md[name]
            cache={ name: sequence }
        else:
            sequence=expr(md)
            cache=None

        if not sequence:
            if self.elses: return render_blocks(self.elses, md)
            return ''

        if type(sequence) is type(''):
            raise ValueError, (
                'Strings are not allowed as input to the in tag.')


        section=self.section
        params=self.args

        mapping=self.mapping
        no_push_item=self.no_push_item

        if self.sort_expr is not None:
            self.sort=self.sort_expr.eval(md)
            sequence=self.sort_sequence(sequence, md)
        elif self.sort is not None:
            sequence=self.sort_sequence(sequence, md)

        if self.reverse_expr is not None and self.reverse_expr.eval(md):
            sequence=self.reverse_sequence(sequence)
        elif self.reverse is not None:
            sequence=self.reverse_sequence(sequence)

        next=previous=0
        try: start=int_param(params,md,'start',0)
        except: start=1
        end=int_param(params,md,'end',0)
        size=int_param(params,md,'size',0)
        overlap=int_param(params,md,'overlap',0)
        orphan=int_param(params,md,'orphan','0')
        start,end,sz=opt(start,end,size,orphan,sequence)
        if params.has_key('next'): next=1
        if params.has_key('previous'): previous=1

        last=end-1
        first=start-1

        try: query_string=md['QUERY_STRING']
        except: query_string=''
        prefix = params.get('prefix')
        vars = sequence_variables(sequence, '?'+query_string,
                                  self.start_name_re, prefix)
        kw=vars.data
        pkw = add_with_prefix(kw, 'sequence', prefix)
        for k, v in kw.items():
            pkw[k] = v
        pkw['sequence-step-size']=sz
        pkw['sequence-step-overlap']=overlap
        pkw['sequence-step-start']=start
        pkw['sequence-step-end']=end
        pkw['sequence-step-start-index']=start-1
        pkw['sequence-step-end-index']=end-1
        pkw['sequence-step-orphan']=orphan

        kw['mapping']=mapping

        push=md._push
        pop=md._pop
        render=render_blocks

        if cache: push(cache)
        push(vars)
        try:
            if previous:
                if first > 0:
                    pstart,pend,psize=opt(0,first+overlap,
                                          sz,orphan,sequence)
                    pkw['previous-sequence']=1
                    pkw['previous-sequence-start-index']=pstart-1
                    pkw['previous-sequence-end-index']=pend-1
                    pkw['previous-sequence-size']=pend+1-pstart
                    result=render(section,md)

                elif self.elses: result=render(self.elses, md)
                else: result=''
            elif next:
                try:
                    # The following line is a sneaky way to test whether
                    # there are more items, without actually
                    # computing a length:
                    sequence[end]
                except IndexError:
                    if self.elses: result=render(self.elses, md)
                    else: result=''
                else:
                    pstart,pend,psize=opt(end+1-overlap,0,
                                          sz,orphan,sequence)
                    pkw['next-sequence']=1
                    pkw['next-sequence-start-index']=pstart-1
                    pkw['next-sequence-end-index']=pend-1
                    pkw['next-sequence-size']=pend+1-pstart
                    result=render(section,md)
            else:
                result = []
                append=result.append
                guarded_getitem = getattr(md, 'guarded_getitem', None)
                for index in range(first,end):
                    # preset
                    pkw['previous-sequence']= 0
                    pkw['next-sequence']= 0 # now more often defined then previously
                    #
                    if index==first or index==last:
                        # provide batching information
                        if first > 0:
                            pstart,pend,psize=opt(0,first+overlap,
                                                  sz,orphan,sequence)
                            if index==first: pkw['previous-sequence']=1
                            pkw['previous-sequence-start-index']=pstart-1
                            pkw['previous-sequence-end-index']=pend-1
                            pkw['previous-sequence-size']=pend+1-pstart
                        try:
                            # The following line is a sneaky way to
                            # test whether there are more items,
                            # without actually computing a length:
                            sequence[end]
                            pstart,pend,psize=opt(end+1-overlap,0,
                                                  sz,orphan,sequence)
                            if index==last: pkw['next-sequence']=1
                            pkw['next-sequence-start-index']=pstart-1
                            pkw['next-sequence-end-index']=pend-1
                            pkw['next-sequence-size']=pend+1-pstart
                        except: pass

                    if index==last: pkw['sequence-end']=1

                    if guarded_getitem is not None:
                        try: client = guarded_getitem(sequence, index)
                        except ValidationError, vv:
                            if (params.has_key('skip_unauthorized') and
                                params['skip_unauthorized']):
                                if index==first: pkw['sequence-start']=0
                                continue
                            raise ValidationError, '(item %s): %s' % (
                                index, vv), sys.exc_info()[2]
                    else:
                        client = sequence[index]

                    pkw['sequence-index']=index
                    t = type(client)
                    if t is TupleType and len(client)==2:
                        client=client[1]

                    if no_push_item:
                        pushed = 0
                    elif mapping:
                        pushed = 1
                        push(client)
                    elif t in StringTypes:
                        pushed = 0
                    else:
                        pushed = 1
                        push(InstanceDict(client, md))

                    try: append(render(section, md))
                    finally:
                        if pushed:
                            pop()

                    if index==first: pkw['sequence-start']=0


                result = join_unicode(result)

        finally:
            if cache: pop()
            pop()

        return result

    def renderwob(self, md):
        """RENDER WithOutBatch"""
        expr=self.expr
        name=self.__name__
        if expr is None:
            sequence=md[name]
            cache={ name: sequence }
        else:
            sequence=expr(md)
            cache=None

        if not sequence:
            if self.elses: return render_blocks(self.elses, md)
            return ''

        if type(sequence) is type(''):
            raise ValueError, (
                'Strings are not allowed as input to the in tag.')

        section=self.section
        mapping=self.mapping
        no_push_item=self.no_push_item

        if self.sort_expr is not None:
            self.sort=self.sort_expr.eval(md)
            sequence=self.sort_sequence(sequence, md)
        elif self.sort is not None:
            sequence=self.sort_sequence(sequence, md)

        if self.reverse_expr is not None and self.reverse_expr.eval(md):
            sequence=self.reverse_sequence(sequence)
        elif self.reverse is not None:
            sequence=self.reverse_sequence(sequence)

        prefix = self.args.get('prefix')
        vars=sequence_variables(sequence, alt_prefix=prefix)
        kw=vars.data
        pkw = add_with_prefix(kw, 'sequence', prefix)
        for k, v in kw.items():
            pkw[k] = v
        kw['mapping']=mapping

        l=len(sequence)
        last=l-1

        push=md._push
        pop=md._pop
        render=render_blocks

        if cache: push(cache)
        push(vars)
        try:
            result = []
            append=result.append
            guarded_getitem = getattr(md, 'guarded_getitem', None)
            for index in range(l):
                if index==last: pkw['sequence-end']=1
                if guarded_getitem is not None:
                    try: client = guarded_getitem(sequence, index)
                    except ValidationError, vv:
                        if (self.args.has_key('skip_unauthorized') and
                            self.args['skip_unauthorized']):
                            if index==1: pkw['sequence-start']=0
                            continue
                        raise ValidationError, '(item %s): %s' % (
                            index, vv), sys.exc_info()[2]
                else:
                    client = sequence[index]

                pkw['sequence-index']=index
                t = type(client)
                if t is TupleType and len(client)==2:
                    client=client[1]

                if no_push_item:
                    pushed = 0
                elif mapping:
                    pushed = 1
                    push(client)
                elif t in StringTypes:
                    pushed = 0
                else:
                    pushed = 1
                    push(InstanceDict(client, md))

                try: append(render(section, md))
                finally:
                    if pushed:
                        pop()
                if index==0: pkw['sequence-start']=0

            result = join_unicode(result)

        finally:
Example #6
0
class InClass(object):
    elses = None
    expr = sort = batch = mapping = no_push_item = None
    start_name_re = None
    reverse = None
    sort_expr = reverse_expr = None

    def __init__(self, blocks, encoding=None):
        tname, args, section = blocks[0]
        args = parse_params(args, name='', start='1', end='-1', size='10',
                            orphan='0', overlap='1', mapping=1,
                            no_push_item=1,
                            skip_unauthorized=1,
                            previous=1, next=1, expr='', sort='',
                            reverse=1, sort_expr='', reverse_expr='',
                            prefix='')
        self.args = args
        self.encoding = encoding

        if 'sort' in args:
            self.sort = sort = args['sort']
            if sort == 'sequence-item':
                self.sort = ''

        if 'sort_expr' in args:
            self.sort_expr = Eval(args['sort_expr'])

        if 'reverse_expr' in args:
            self.reverse_expr = Eval(args['reverse_expr'])

        if 'reverse' in args:
            self.reverse = args['reverse']

        if 'no_push_item' in args:
            self.no_push_item = args['no_push_item']

        if 'mapping' in args:
            self.mapping = args['mapping']
        for n in 'start', 'size', 'end':
            if n in args:
                self.batch = 1

        prefix = args.get('prefix')
        if prefix and not simple_name(prefix):
            raise ParseError('prefix is not a simple name', 'in')

        for n in ('orphan', 'overlap', 'previous', 'next'):
            if n in args and not self.batch:
                raise ParseError(
                    """
                    The %s attribute was used but neither of the
                    <code>start</code>, <code>end</code>, or <code>size</code>
                    attributes were used.
                    """ % n, 'in')

        if 'start' in args:
            v = args['start']
            if isinstance(v, str):
                try:
                    int(v)
                except Exception:
                    self.start_name_re = re.compile(
                        '&+' +
                        ''.join(["[%s]" % c for c in v]) +
                        '=[0-9]+&+')

        name, expr = name_param(args, 'in', 1)
        if expr is not None:
            expr = expr.eval
        self.__name__, self.expr = name, expr
        self.section = section.blocks
        if len(blocks) > 1:
            if len(blocks) != 2:
                raise ParseError('too many else blocks', 'in')
            tname, args, section = blocks[1]
            args = parse_params(args, name='')
            if args:
                ename = name_param(args)
                if ename != name:
                    raise ParseError('name in else does not match in', 'in')
            self.elses = section.blocks

    def renderwb(self, md):
        expr = self.expr
        name = self.__name__
        if expr is None:
            sequence = md[name]
            cache = {name: sequence}
        else:
            sequence = expr(md)
            cache = None

        if not sequence:
            if self.elses:
                return render_blocks(self.elses, md, encoding=self.encoding)
            return ''

        if isinstance(sequence, str):
            raise ValueError(
                'Strings are not allowed as input to the in tag.')

        # Turn iterable like dict.keys() into a list.
        sequence = list(sequence)
        if cache is not None:
            cache[name] = sequence

        section = self.section
        params = self.args

        mapping = self.mapping
        no_push_item = self.no_push_item

        if self.sort_expr is not None:
            self.sort = self.sort_expr.eval(md)
            sequence = self.sort_sequence(sequence, md)
        elif self.sort is not None:
            sequence = self.sort_sequence(sequence, md)

        if self.reverse_expr is not None and self.reverse_expr.eval(md):
            sequence = self.reverse_sequence(sequence)
        elif self.reverse is not None:
            sequence = self.reverse_sequence(sequence)

        next = previous = 0
        try:
            start = int_param(params, md, 'start', 0)
        except Exception:
            start = 1
        end = int_param(params, md, 'end', 0)
        size = int_param(params, md, 'size', 0)
        overlap = int_param(params, md, 'overlap', 0)
        orphan = int_param(params, md, 'orphan', '0')
        start, end, sz = opt(start, end, size, orphan, sequence)
        if 'next' in params:
            next = 1
        if 'previous' in params:
            previous = 1

        last = end - 1
        first = start - 1

        try:
            query_string = md['QUERY_STRING']
        except Exception:
            query_string = ''
        prefix = params.get('prefix')
        vars = sequence_variables(sequence, '?' + query_string,
                                  self.start_name_re, prefix)
        kw = vars.data
        pkw = add_with_prefix(kw, 'sequence', prefix)
        for k, v in list(kw.items()):
            pkw[k] = v
        pkw['sequence-step-size'] = sz
        pkw['sequence-step-overlap'] = overlap
        pkw['sequence-step-start'] = start
        pkw['sequence-step-end'] = end
        pkw['sequence-step-start-index'] = start - 1
        pkw['sequence-step-end-index'] = end - 1
        pkw['sequence-step-orphan'] = orphan

        kw['mapping'] = mapping

        push = md._push
        pop = md._pop
        render = render_blocks

        if cache:
            push(cache)
        push(vars)
        try:
            if previous:
                if first > 0:
                    pstart, pend, psize = opt(0, first + overlap,
                                              sz, orphan, sequence)
                    pkw['previous-sequence'] = 1
                    pkw['previous-sequence-start-index'] = pstart - 1
                    pkw['previous-sequence-end-index'] = pend - 1
                    pkw['previous-sequence-size'] = pend + 1 - pstart
                    result = render(section, md, encoding=self.encoding)

                elif self.elses:
                    result = render(self.elses, md, encoding=self.encoding)
                else:
                    result = ''
            elif next:
                try:
                    # The following line is a sneaky way to test whether
                    # there are more items, without actually
                    # computing a length:
                    sequence[end]
                except IndexError:
                    if self.elses:
                        result = render(self.elses, md, encoding=self.encoding)
                    else:
                        result = ''
                else:
                    pstart, pend, psize = opt(end + 1 - overlap, 0,
                                              sz, orphan, sequence)
                    pkw['next-sequence'] = 1
                    pkw['next-sequence-start-index'] = pstart - 1
                    pkw['next-sequence-end-index'] = pend - 1
                    pkw['next-sequence-size'] = pend + 1 - pstart
                    result = render(section, md, encoding=self.encoding)
            else:
                result = []
                append = result.append
                guarded_getitem = getattr(md, 'guarded_getitem', None)
                for index in range(first, end):
                    # preset
                    pkw['previous-sequence'] = 0
                    # now more often defined then previously
                    pkw['next-sequence'] = 0
                    #
                    if index == first or index == last:
                        # provide batching information
                        if first > 0:
                            pstart, pend, psize = opt(0, first + overlap,
                                                      sz, orphan, sequence)
                            if index == first:
                                pkw['previous-sequence'] = 1
                            pkw['previous-sequence-start-index'] = pstart - 1
                            pkw['previous-sequence-end-index'] = pend - 1
                            pkw['previous-sequence-size'] = pend + 1 - pstart
                        try:
                            # The following line is a sneaky way to
                            # test whether there are more items,
                            # without actually computing a length:
                            sequence[end]
                            pstart, pend, psize = opt(end + 1 - overlap, 0,
                                                      sz, orphan, sequence)
                            if index == last:
                                pkw['next-sequence'] = 1
                            pkw['next-sequence-start-index'] = pstart - 1
                            pkw['next-sequence-end-index'] = pend - 1
                            pkw['next-sequence-size'] = pend + 1 - pstart
                        except Exception:
                            pass

                    if index == last:
                        pkw['sequence-end'] = 1

                    if guarded_getitem is not None:
                        try:
                            client = guarded_getitem(sequence, index)
                        except ValidationError as vv:
                            if ('skip_unauthorized' in params and
                                    params['skip_unauthorized']):
                                if index == first:
                                    pkw['sequence-start'] = 0
                                continue
                            raise ValidationError('(item %s): %s' % (
                                index, vv), sys.exc_info()[2])
                    else:
                        client = sequence[index]

                    pkw['sequence-index'] = index
                    t = type(client)
                    if t is TupleType and len(client) == 2:
                        client = client[1]

                    if no_push_item:
                        pushed = 0
                    elif mapping:
                        pushed = 1
                        push(client)
                    elif t in StringTypes:
                        pushed = 0
                    else:
                        pushed = 1
                        push(InstanceDict(client, md))

                    try:
                        append(render(section, md, encoding=self.encoding))
                    finally:
                        if pushed:
                            pop()

                    if index == first:
                        pkw['sequence-start'] = 0

                result = join_unicode(result, encoding=self.encoding)

        finally:
            if cache:
                pop()
            pop()

        return result

    def renderwob(self, md):
        """RENDER WithOutBatch"""
        expr = self.expr
        name = self.__name__
        if expr is None:
            sequence = md[name]
            cache = {name: sequence}
        else:
            sequence = expr(md)
            cache = None

        if not sequence:
            if self.elses:
                return render_blocks(self.elses, md, encoding=self.encoding)
            return ''

        if isinstance(sequence, str):
            raise ValueError(
                'Strings are not allowed as input to the in tag.')

        # Turn iterable like dict.keys() into a list.
        sequence = list(sequence)
        if cache is not None:
            cache[name] = sequence

        section = self.section
        mapping = self.mapping
        no_push_item = self.no_push_item

        if self.sort_expr is not None:
            self.sort = self.sort_expr.eval(md)
            sequence = self.sort_sequence(sequence, md)
        elif self.sort is not None:
            sequence = self.sort_sequence(sequence, md)

        if self.reverse_expr is not None and self.reverse_expr.eval(md):
            sequence = self.reverse_sequence(sequence)
        elif self.reverse is not None:
            sequence = self.reverse_sequence(sequence)

        prefix = self.args.get('prefix')
        vars = sequence_variables(sequence, alt_prefix=prefix)
        kw = vars.data
        pkw = add_with_prefix(kw, 'sequence', prefix)
        for k, v in list(kw.items()):
            pkw[k] = v
        kw['mapping'] = mapping

        l_ = len(sequence)
        last = l_ - 1

        push = md._push
        pop = md._pop
        render = render_blocks

        if cache:
            push(cache)
        push(vars)
        try:
            result = []
            append = result.append
            guarded_getitem = getattr(md, 'guarded_getitem', None)
            for index in range(l_):
                if index == last:
                    pkw['sequence-end'] = 1
                if guarded_getitem is not None:
                    try:
                        client = guarded_getitem(sequence, index)
                    except ValidationError as vv:
                        if ('skip_unauthorized' in self.args and
                                self.args['skip_unauthorized']):
                            if index == 1:
                                pkw['sequence-start'] = 0
                            continue
                        raise ValidationError(
                            '(item %s): %s' % (index, vv), sys.exc_info()[2])
                else:
                    client = sequence[index]

                pkw['sequence-index'] = index
                t = type(client)
                if t is TupleType and len(client) == 2:
                    client = client[1]

                if no_push_item:
                    pushed = 0
                elif mapping:
                    pushed = 1
                    push(client)
                elif t in StringTypes:
                    pushed = 0
                else:
                    pushed = 1
                    push(InstanceDict(client, md))

                try:
                    append(render(section, md, encoding=self.encoding))
                finally:
                    if pushed:
                        pop()
                if index == 0:
                    pkw['sequence-start'] = 0

            result = join_unicode(result, encoding=self.encoding)

        finally:
            if cache:
                pop()
            pop()

        return result

    def sort_sequence(self, sequence, md):

        # Modified with multiple sort fields by Ross Lazarus
        # April 7 2000 [email protected]
        # eg <dtml-in "foo" sort="akey,anotherkey">

        # Modified with advanced sort functions by
        # Oleg Broytmann <*****@*****.**> 30 Mar 2001
        # eg <dtml-in "foo" sort="akey/nocase,anotherkey/cmp/desc">

        sort = self.sort
        need_sortfunc = sort.find('/') >= 0

        sortfields = sort.split(',')  # multi sort = key1,key2
        multsort = len(sortfields) > 1  # flag: is multiple sort

        if need_sortfunc:
            # prepare the list of functions and sort order multipliers
            sf_list = make_sortfunctions(sortfields, md)

            # clean the mess a bit
            if multsort:  # More than one sort key.
                sortfields = tuple(map(lambda x: x[0], sf_list))
            else:
                sort = sf_list[0][0]

        mapping = self.mapping
        isort = not sort

        s = []
        for client in sequence:
            k = None
            if type(client) == TupleType and len(client) == 2:
                if isort:
                    k = client[0]
                v = client[1]
            else:
                if isort:
                    k = client
                v = client

            if sort:
                if multsort:  # More than one sort key.
                    k = []
                    for sk in sortfields:
                        if mapping:
                            akey = v.get(sk)
                        else:
                            akey = getattr(v, sk, None)
                        if not basic_type(akey):
                            try:
                                akey = akey()
                            except Exception:
                                pass
                        k.append(akey)
                else:  # One sort key.
                    if mapping:
                        k = v.get(sort)
                    else:
                        k = getattr(v, sort, None)
                    if not basic_type(type(k)):
                        try:
                            k = k()
                        except Exception:
                            k = _Smallest

            s.append((k, client))

        if need_sortfunc:
            by = SortBy(multsort, sf_list)
            s.sort(key=functools.cmp_to_key(by))
        else:
            # In python 3 a key is required when tuples in the list have
            # the same sort key to prevent attempting to compare the second
            # item which is dict.
            s.sort(key=itemgetter(0))

        sequence = []
        for k, client in s:
            sequence.append(client)
        return sequence

    def reverse_sequence(self, sequence):
        s = list(sequence)
        s.reverse()
        return s