Пример #1
0
    def __init__(self, context, blocks):
        tname, args, section = blocks[0]
        args=parse_params(args, name='', start='1',end='-1',size='10',
                          orphan='3',overlap='1',mapping=1,
                          skip_unauthorized=1,
                          previous=1, next=1, expr='', sort='',
                          reverse=1, sort_expr='', reverse_expr='')
        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(context, args['sort_expr'])

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

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

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

        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 isinstance(v, StringType):
                try: v.atoi()
                except:
                    self.start_name_re = re.compile(
                        '&+'+
                        ''.join(map(lambda c: "[%s]" % c, v))+
                        '=[0-9]+&+')

        name, expr = name_param(context, 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(context, args)
                if ename != name:
                    raise ParseError(
                        'name in else does not match in', 'in')
            self.elses = section.blocks
Пример #2
0
class InClass:
    elses = None
    expr = sort = batch = mapping = None
    start_name_re = None
    reverse = None
    sort_expr = reverse_expr = None

    def __init__(self, context, blocks):
        tname, args, section = blocks[0]
        args=parse_params(args, name='', start='1',end='-1',size='10',
                          orphan='3',overlap='1',mapping=1,
                          skip_unauthorized=1,
                          previous=1, next=1, expr='', sort='',
                          reverse=1, sort_expr='', reverse_expr='')
        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(context, args['sort_expr'])

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

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

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

        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 isinstance(v, StringType):
                try: v.atoi()
                except:
                    self.start_name_re = re.compile(
                        '&+'+
                        ''.join(map(lambda c: "[%s]" % c, v))+
                        '=[0-9]+&+')

        name, expr = name_param(context, 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(context, 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, StringType):
            raise InError('Strings are not allowed as input to the in tag.')


        section = self.section
        params = self.args

        mapping = self.mapping

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

        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', '3')
        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 = ''

        vars = sequence_variables(sequence,'?' + query_string,
                                  self.start_name_re)
        kw = vars.data
        kw['mapping'] = mapping
        kw['sequence-step-size'] = sz
        kw['sequence-step-overlap'] = overlap
        kw['sequence-step-start'] = start
        kw['sequence-step-end'] = end
        kw['sequence-step-start-index'] = start - 1
        kw['sequence-step-end-index'] = end - 1
        kw['sequence-step-orphan'] = orphan

        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)
                    kw['previous-sequence'] = 1
                    kw['previous-sequence-start-index'] = pstart - 1
                    kw['previous-sequence-end-index'] = pend - 1
                    kw['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)
                    kw['next-sequence'] = 1
                    kw['next-sequence-start-index'] = pstart - 1
                    kw['next-sequence-end-index'] = pend - 1
                    kw['next-sequence-size'] = pend + 1 - pstart
                    result = render(section, md)
            else:
                result = []
                append = result.append
                validate = md.validate
                for index in range(first,end):
                    # preset
                    kw['previous-sequence'] = 0
                    # now more often defined then previously
                    kw['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:
                                kw['previous-sequence'] = 1
                            kw['previous-sequence-start-index'] = pstart - 1
                            kw['previous-sequence-end-index'] = pend - 1
                            kw['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:
                                kw['next-sequence'] = 1
                            kw['next-sequence-start-index'] = pstart - 1
                            kw['next-sequence-end-index'] = pend - 1
                            kw['next-sequence-size'] = pend + 1 - pstart
                        except:
                            pass

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

                    client = sequence[index]

                    if validate is not None:
                        try:
                            vv = validate(sequence, sequence, None, client,md)
                        except:
                            vv = 0
                        if not vv:
                            if (params.has_key('skip_unauthorized') and
                                params['skip_unauthorized']):
                                if index == first:
                                    kw['sequence-start'] = 0
                                continue
                            raise ValidationError(index)

                    kw['sequence-index'] = index
                    if isinstance(client, TupleType) and len(client) == 2:
                        client = client[1]

                    if mapping:
                        push(client)
                    else:
                        md._push_instance(client)

                    try:
                        append(render(section, md))
                    finally:
                        pop(1)

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

                result = ''.join(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, StringType):
            raise InError('Strings are not allowed as input to the in tag.')

        section = self.section
        mapping = self.mapping


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

        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)

        vars = sequence_variables(sequence)
        kw = vars.data
        kw['mapping'] = mapping

        l = len(sequence)
        last = l - 1

        push = md._push
        pop = md._pop
        render = render_blocks
        get = self.args.get

        if cache:
            push(cache)
        push(vars)
        try:
            result = []
            append = result.append
            validate = md.validate
            for index in range(l):
                if index == last:
                    kw['sequence-end'] = 1
                client = sequence[index]

                if validate is not None:
                    try:
                        vv = validate(sequence, sequence, None, client, md)
                    except:
                        vv = 0
                    if not vv:
                        if get('skip_unauthorized'):
                            if index == 1:
                                kw['sequence-start'] = 0
                            continue
                        raise ValidationError(index)

                kw['sequence-index'] = index
                if isinstance(client, TupleType) and len(client) == 2:
                    client = client[1]

                if mapping:
                    push(client)
                else:
                    md._push_instance(client)

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

            result = ''.join(result)

        finally:
            if cache:
                pop()
            pop()

        return result

    def sort_sequence(self, sequence):

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

        sort = self.sort
        sortfields = sort.split(',')   # multi sort = key1,key2
        multsort = len(sortfields) > 1 # flag: is multiple sort
        mapping = self.mapping
        isort = not sort
        s = []
        for client in sequence:
            k = None
            if isinstance(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:
                        try:
                            if mapping:
                                akey = v[sk]
                            else:
                                akey = getattr(v, sk)
                        except AttributeError, KeyError:
                            akey = None
                        if not basic_type(akey):
                            try:
                                akey = akey()
                            except:
                                pass
                        k.append(akey)
                else: # One sort key.
                    try:
                        if mapping:
                            k = v[sort]
                        else:
                            k = getattr(v, sort)
                    except AttributeError, KeyError:
                        k = None
                    if not basic_type(type(k)):
                        try:
                            k = k()
                        except:
                            pass

            s.append((k,client))