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
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))