Skip to content
This repository
Browse code

a clean restart

--HG--
branch : trunk
rename : jinja/__init__.py => jinja2/__init__.py
rename : jinja/_debugger.c => jinja2/_debugger.c
rename : jinja/_native.py => jinja2/_native.py
rename : jinja/_speedups.c => jinja2/_speedups.c
rename : jinja/constants.py => jinja2/constants.py
rename : jinja/contrib/__init__.py => jinja2/contrib/__init__.py
rename : jinja/contrib/_djangosupport.py => jinja2/contrib/_djangosupport.py
rename : jinja/contrib/djangosupport.py => jinja2/contrib/djangosupport.py
rename : jinja/datastructure.py => jinja2/datastructure.py
rename : jinja/defaults.py => jinja2/defaults.py
rename : jinja/environment.py => jinja2/environment.py
rename : jinja/exceptions.py => jinja2/exceptions.py
rename : jinja/filters.py => jinja2/filters.py
rename : jinja/lexer.py => jinja2/lexer.py
rename : jinja/loaders.py => jinja2/loaders.py
rename : jinja/nodes.py => jinja2/nodes.py
rename : jinja/parser.py => jinja2/parser.py
rename : jinja/tests.py => jinja2/tests.py
rename : jinja/translators/__init__.py => jinja2/translators/__init__.py
rename : jinja/translators/python.py => jinja2/translators/python.py
rename : jinja/utils.py => jinja2/utils.py
  • Loading branch information...
commit 07bc684ccdbf4bfabbf81de1ecdfa531e65f923a 1 parent e074cd2
Armin Ronacher authored

Showing 30 changed files with 863 additions and 5,084 deletions. Show diff stats Hide diff stats

  1. +0 708 jinja/datastructure.py
  2. +0 213 jinja/debugger.py
  3. +0 404 jinja/environment.py
  4. +0 91 jinja/exceptions.py
  5. +0 825 jinja/loaders.py
  6. +0 792 jinja/nodes.py
  7. +0 1,187 jinja/parser.py
  8. +0 166 jinja/plugin.py
  9. +0 645 jinja/utils.py
  10. +3 21 {jinja → jinja2}/__init__.py
  11. 0  {jinja → jinja2}/_debugger.c
  12. 0  {jinja → jinja2}/_native.py
  13. 0  {jinja → jinja2}/_speedups.c
  14. 0  {jinja → jinja2}/constants.py
  15. 0  {jinja → jinja2}/contrib/__init__.py
  16. 0  {jinja → jinja2}/contrib/_djangosupport.py
  17. 0  {jinja → jinja2}/contrib/djangosupport.py
  18. +137 0 jinja2/datastructure.py
  19. +1 1  {jinja → jinja2}/defaults.py
  20. +115 0 jinja2/environment.py
  21. +42 0 jinja2/exceptions.py
  22. +0 4 {jinja → jinja2}/filters.py
  23. +12 27 {jinja → jinja2}/lexer.py
  24. +10 0 jinja2/loaders.py
  25. +494 0 jinja2/nodes.py
  26. +39 0 jinja2/parser.py
  27. 0  {jinja → jinja2}/tests.py
  28. 0  {jinja → jinja2}/translators/__init__.py
  29. 0  {jinja → jinja2}/translators/python.py
  30. +10 0 jinja2/utils.py
708 jinja/datastructure.py
... ... @@ -1,708 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -"""
3   - jinja.datastructure
4   - ~~~~~~~~~~~~~~~~~~~
5   -
6   - Module that helds several data types used in the template engine.
7   -
8   - :copyright: 2007 by Armin Ronacher.
9   - :license: BSD, see LICENSE for more details.
10   -"""
11   -from jinja.exceptions import TemplateSyntaxError, TemplateRuntimeError
12   -
13   -_missing = object()
14   -
15   -
16   -def contextcallable(f):
17   - """
18   - Mark a function context callable.
19   - """
20   - f.jinja_context_callable = True
21   - return f
22   -
23   -
24   -def unsafe(f):
25   - """
26   - Mark function as unsafe.
27   - """
28   - f.jinja_unsafe_call = True
29   - return f
30   -
31   -
32   -def make_undefined(implementation):
33   - """
34   - Creates an undefined singleton based on a given implementation.
35   - It performs some tests that make sure the undefined type implements
36   - everything it should.
37   - """
38   - self = object.__new__(implementation)
39   - self.__reduce__()
40   - return self
41   -
42   -
43   -class AbstractUndefinedType(object):
44   - """
45   - Base class for any undefined type.
46   - """
47   - __slots__ = ()
48   -
49   - def __init__(self):
50   - raise TypeError('cannot create %r instances' %
51   - self.__class__.__name__)
52   -
53   - def __setattr__(self, name, value):
54   - raise AttributeError('%r object has no attribute %r' % (
55   - self.__class__.__name__,
56   - name
57   - ))
58   -
59   - def __eq__(self, other):
60   - return self is other
61   -
62   - def __ne__(self, other):
63   - return self is not other
64   -
65   - def __copy__(self):
66   - return self
67   - __deepcopy__ = __copy__
68   -
69   - def __repr__(self):
70   - return 'Undefined'
71   -
72   - def __reduce__(self):
73   - raise TypeError('undefined objects have to provide a __reduce__')
74   -
75   -
76   -class SilentUndefinedType(AbstractUndefinedType):
77   - """
78   - An object that does not exist.
79   - """
80   - __slots__ = ()
81   -
82   - def __add__(self, other):
83   - """Any operator returns the operand."""
84   - return other
85   - __sub__ = __mul__ = __div__ = __rsub__ = __rmul__ = __div__ = __mod__ =\
86   - __radd__ = __rmod__ = __add__
87   -
88   - def __getitem__(self, arg):
89   - """Getting any item returns `Undefined`"""
90   - return self
91   -
92   - def __iter__(self):
93   - """Iterating over `Undefined` returns an empty iterator."""
94   - if False:
95   - yield None
96   -
97   - def __getattr__(self, arg):
98   - """Getting any attribute returns `Undefined`"""
99   - return self
100   -
101   - def __nonzero__(self):
102   - """`Undefined` is considered boolean `False`"""
103   - return False
104   -
105   - def __len__(self):
106   - """`Undefined` is an empty sequence"""
107   - return 0
108   -
109   - def __str__(self):
110   - """The string representation is empty."""
111   - return ''
112   -
113   - def __unicode__(self):
114   - """The unicode representation is empty."""
115   - return u''
116   -
117   - def __int__(self):
118   - """Converting `Undefined` to an integer ends up in ``0``"""
119   - return 0
120   -
121   - def __float__(self):
122   - """Converting `Undefined` to an float ends up in ``0.0``"""
123   - return 0.0
124   -
125   - def __call__(self, *args, **kwargs):
126   - """Calling `Undefined` returns `Undefined`"""
127   - return self
128   -
129   - def __reduce__(self):
130   - """Helper for pickle."""
131   - return 'SilentUndefined'
132   -
133   -
134   -class ComplainingUndefinedType(AbstractUndefinedType):
135   - """
136   - An object that does not exist.
137   - """
138   - __slots__ = ()
139   -
140   - def __len__(self):
141   - """Getting the length raises error."""
142   - raise TemplateRuntimeError('Operated on undefined object')
143   -
144   - def __iter__(self):
145   - """Iterating over `Undefined` raises an error."""
146   - raise TemplateRuntimeError('Iterated over undefined object')
147   -
148   - def __nonzero__(self):
149   - """`Undefined` is considered boolean `False`"""
150   - return False
151   -
152   - def __str__(self):
153   - """The string representation raises an error."""
154   - raise TemplateRuntimeError('Undefined object rendered')
155   -
156   - def __unicode__(self):
157   - """The unicode representation raises an error."""
158   - self.__str__()
159   -
160   - def __call__(self, *args, **kwargs):
161   - """Calling `Undefined` returns `Undefined`"""
162   - raise TemplateRuntimeError('Undefined object called')
163   -
164   - def __reduce__(self):
165   - """Helper for pickle."""
166   - return 'ComplainingUndefined'
167   -
168   -
169   -#: the singleton instances for the undefined objects
170   -SilentUndefined = make_undefined(SilentUndefinedType)
171   -ComplainingUndefined = make_undefined(ComplainingUndefinedType)
172   -
173   -#: jinja 1.0 compatibility
174   -Undefined = SilentUndefined
175   -UndefinedType = SilentUndefinedType
176   -
177   -
178   -class FakeTranslator(object):
179   - """
180   - Default null translator.
181   - """
182   -
183   - def gettext(self, s):
184   - """
185   - Translate a singular string.
186   - """
187   - return s
188   -
189   - def ngettext(self, s, p, n):
190   - """
191   - Translate a plural string.
192   - """
193   - if n == 1:
194   - return s
195   - return p
196   -
197   -
198   -class Deferred(object):
199   - """
200   - Object marking an deferred value. Deferred objects are
201   - objects that are called first access in the context.
202   - """
203   -
204   - def __init__(self, factory):
205   - self.factory = factory
206   -
207   - def __call__(self, context, name):
208   - return self.factory(context.environment, context, name)
209   -
210   -
211   -class Markup(unicode):
212   - """
213   - Compatibility for Pylons and probably some other frameworks.
214   -
215   - It's only used in Jinja environments with `auto_escape` set
216   - to true.
217   - """
218   -
219   - def __html__(self):
220   - return unicode(self)
221   -
222   -
223   -class TemplateData(Markup):
224   - """
225   - Subclass of unicode to mark objects that are coming from the
226   - template. The autoescape filter can use that.
227   - """
228   -
229   -
230   -# import these here because those modules import Deferred and Undefined
231   -# from this module.
232   -try:
233   - # try to use the c implementation of the base context if available
234   - from jinja._speedups import BaseContext
235   -except ImportError:
236   - # if there is no c implementation we go with a native python one
237   - from jinja._native import BaseContext
238   -
239   -
240   -class Context(BaseContext):
241   - """
242   - Dict like object containing the variables for the template.
243   - """
244   -
245   - def __init__(self, *args, **kwargs):
246   - environment = args[0]
247   - if not kwargs and len(args) == 2 and isinstance(args[1], dict):
248   - base = args[1]
249   - else:
250   - base = dict(*args[1:], **kwargs)
251   - super(Context, self).__init__(environment.undefined_singleton,
252   - environment.globals, base)
253   - self._translate_func = None
254   - self.cache = {}
255   - self.environment = environment
256   -
257   - def to_dict(self):
258   - """
259   - Convert the context into a dict. This skips the globals.
260   - """
261   - result = {}
262   - for layer in self.stack[1:]:
263   - for key, value in layer.iteritems():
264   - if key.startswith('::'):
265   - continue
266   - result[key] = value
267   - return result
268   -
269   - def set_nonlocal(self, name, value):
270   - """
271   - Set a value in an outer scope.
272   - """
273   - for layer in self.stack[:0:-1]:
274   - if name in layer:
275   - layer[name] = value
276   - return
277   - self.initial[name] = value
278   -
279   - def translate_func(self):
280   - """
281   - The translation function for this context. It takes
282   - 4 parameters. The singular string, the optional plural one,
283   - The name of the variable in the replacements dict and the
284   - replacements dict. This is only used by the i18n system
285   - internally the simplified version (just one argument) is
286   - available in the template for the user too.
287   - """
288   - if self._translate_func is not None:
289   - return self._translate_func
290   - translator = self.environment.get_translator(self)
291   - gettext = translator.gettext
292   - ngettext = translator.ngettext
293   - def translate(s, p=None, n=None, r=None):
294   - if p is None:
295   - s = gettext(s)
296   - else:
297   - s = ngettext(s, p, r[n])
298   - # apply replacement substitution only if replacements
299   - # are given. This is the case for {% trans %}...{% endtrans %}
300   - # but for the "_()" syntax and a trans tag without a body.
301   - if r is not None:
302   - return s % r
303   - return s
304   - translate.__doc__ = Context.translate_func.__doc__
305   - self._translate_func = translate
306   - return translate
307   - translate_func = property(translate_func, doc=translate_func.__doc__)
308   -
309   - def __repr__(self):
310   - """
311   - String representation of the context.
312   - """
313   - return 'Context(%r)' % self.to_dict()
314   -
315   - def __pretty__(self, p, cycle):
316   - if cycle:
317   - return p.text('Context({...})')
318   - p.begin_group(9, 'Context({')
319   - for idx, (key, value) in enumerate(self.to_dict().iteritems()):
320   - if idx:
321   - p.text(',')
322   - p.breakable()
323   - p.pretty(key)
324   - p.text(': ')
325   - p.pretty(value)
326   - p.end_group(9, '})')
327   -
328   -
329   -class LoopContext(object):
330   - """
331   - Simple class that provides special loop variables.
332   - Used by `Environment.iterate`.
333   - """
334   -
335   - jinja_allowed_attributes = ['index', 'index0', 'length', 'parent',
336   - 'even', 'odd', 'revindex0', 'revindex',
337   - 'first', 'last']
338   -
339   - def __init__(self, seq, parent, loop_function):
340   - self.loop_function = loop_function
341   - self.parent = parent
342   - self._stack = []
343   - if loop_function is None:
344   - self.push(seq)
345   -
346   - def push(self, seq):
347   - """
348   - Push a sequence to the loop stack. This is used by the
349   - recursive for loop.
350   - """
351   - # iteration over None is catched, but we don't catch iteration
352   - # over undefined because that behavior is handled in the
353   - # undefined singleton
354   - if seq is None:
355   - seq = ()
356   - length = 0
357   - else:
358   - try:
359   - length = len(seq)
360   - except (AttributeError, TypeError):
361   - seq = list(seq)
362   - length = len(seq)
363   - self._stack.append({
364   - 'index': -1,
365   - 'seq': seq,
366   - 'length': length
367   - })
368   - return self
369   -
370   - def pop(self):
371   - """Remove the last layer from the loop stack."""
372   - return self._stack.pop()
373   -
374   - iterated = property(lambda s: s._stack[-1]['index'] > -1)
375   - index0 = property(lambda s: s._stack[-1]['index'])
376   - index = property(lambda s: s._stack[-1]['index'] + 1)
377   - revindex0 = property(lambda s: s._stack[-1]['length'] -
378   - s._stack[-1]['index'] - 1)
379   - revindex = property(lambda s: s._stack[-1]['length'] -
380   - s._stack[-1]['index'])
381   - length = property(lambda s: s._stack[-1]['length'])
382   - even = property(lambda s: s._stack[-1]['index'] % 2 == 1)
383   - odd = property(lambda s: s._stack[-1]['index'] % 2 == 0)
384   - first = property(lambda s: s._stack[-1]['index'] == 0)
385   - last = property(lambda s: s._stack[-1]['index'] ==
386   - s._stack[-1]['length'] - 1)
387   -
388   - def __iter__(self):
389   - s = self._stack[-1]
390   - for idx, item in enumerate(s['seq']):
391   - s['index'] = idx
392   - yield item
393   -
394   - def __len__(self):
395   - return self._stack[-1]['length']
396   -
397   - def __call__(self, seq):
398   - if self.loop_function is not None:
399   - return self.loop_function(seq)
400   - raise TemplateRuntimeError('In order to make loops callable you have '
401   - 'to define them with the "recursive" '
402   - 'modifier.')
403   -
404   - def __repr__(self):
405   - if self._stack:
406   - return '<LoopContext %d/%d%s>' % (
407   - self.index,
408   - self.length,
409   - self.loop_function is not None and ' recursive' or ''
410   - )
411   - return '<LoopContext (empty)>'
412   -
413   -
414   -class CycleContext(object):
415   - """
416   - Helper class used for cycling.
417   - """
418   -
419   - def __init__(self, seq=None):
420   - self.pos = -1
421   - # bind the correct helper function based on the constructor signature
422   - if seq is not None:
423   - self.seq = seq
424   - self.length = len(seq)
425   - self.cycle = self.cycle_static
426   - else:
427   - self.cycle = self.cycle_dynamic
428   -
429   - def cycle_static(self):
430   - """Helper function for static cycling."""
431   - self.pos = (self.pos + 1) % self.length
432   - return self.seq[self.pos]
433   -
434   - def cycle_dynamic(self, seq):
435   - """Helper function for dynamic cycling."""
436   - self.pos = pos = (self.pos + 1) % len(seq)
437   - return seq[pos]
438   -
439   -
440   -class SuperBlock(object):
441   - """
442   - Helper class for ``{{ super() }}``.
443   - """
444   - jinja_allowed_attributes = ['name']
445   -
446   - def __init__(self, name, blocks, level, context):
447   - self.name = name
448   - self.context = context
449   - if name in blocks:
450   - self.stack = blocks[name]
451   - self.level = level
452   - else:
453   - self.stack = None
454   -
455   - def __call__(self, offset=1):
456   - if self.stack is not None:
457   - level = self.level + (offset - 1)
458   - if level < len(self.stack):
459   - return self.stack[level](self.context)
460   - raise TemplateRuntimeError('no super block for %r' % self.name)
461   -
462   - def __repr__(self):
463   - return '<SuperBlock %r>' % self.name
464   -
465   -
466   -class StateTest(object):
467   - """
468   - Wrapper class for basic lambdas in order to simplify
469   - debugging in the parser. It also provides static helper
470   - functions that replace some lambda expressions
471   - """
472   -
473   - def __init__(self, func, msg):
474   - self.func = func
475   - self.msg = msg
476   -
477   - def __call__(self, token):
478   - return self.func(token)
479   -
480   - def expect_token(*types, **kw):
481   - """Scans until one of the given tokens is found."""
482   - msg = kw.pop('msg', None)
483   - if kw:
484   - raise TypeError('unexpected keyword argument %r' % iter(kw).next())
485   - if len(types) == 1:
486   - if msg is None:
487   - msg = "expected '%s'" % types[0]
488   - return StateTest(lambda t: t.type == types[0], msg)
489   - if msg is None:
490   - msg = 'expected one of %s' % ', '.join(["'%s'" % type
491   - for type in types])
492   - return StateTest(lambda t: t.type in types, msg)
493   - expect_token = staticmethod(expect_token)
494   -
495   -
496   -class Token(object):
497   - """
498   - Token class.
499   - """
500   - __slots__ = ('lineno', 'type', 'value')
501   -
502   - def __init__(self, lineno, type, value):
503   - self.lineno = lineno
504   - self.type = intern(str(type))
505   - self.value = value
506   -
507   - def __str__(self):
508   - from jinja.lexer import keywords, reverse_operators
509   - if self.type in keywords:
510   - return self.type
511   - elif self.type in reverse_operators:
512   - return reverse_operators[self.type]
513   - return self.value
514   -
515   - def __repr__(self):
516   - return 'Token(%r, %r, %r)' % (
517   - self.lineno,
518   - self.type,
519   - self.value
520   - )
521   -
522   -
523   -class TokenStreamIterator(object):
524   - """
525   - The iterator for tokenstreams. Iterate over the stream
526   - until the eof token is reached.
527   - """
528   -
529   - def __init__(self, stream):
530   - self._stream = stream
531   -
532   - def __iter__(self):
533   - return self
534   -
535   - def next(self):
536   - token = self._stream.current
537   - if token.type == 'eof':
538   - self._stream.close()
539   - raise StopIteration()
540   - self._stream.next()
541   - return token
542   -
543   -
544   -class TokenStream(object):
545   - """
546   - A token stream wraps a generator and supports pushing tokens back.
547   - It also provides some functions to expect tokens and similar stuff.
548   -
549   - Important note: Do never push more than one token back to the
550   - stream. Although the stream object won't stop you
551   - from doing so, the behavior is undefined. Multiple
552   - pushed tokens are only used internally!
553   - """
554   -
555   - def __init__(self, generator, filename):
556   - self._next = generator.next
557   - self._pushed = []
558   - self.current = Token(1, 'initial', '')
559   - self.filename = filename
560   - self.next()
561   -
562   - def __iter__(self):
563   - return TokenStreamIterator(self)
564   -
565   - def bound(self):
566   - """Return True if the token stream is bound to a parser."""
567   - return self.parser is not None
568   - bound = property(bound, doc=bound.__doc__)
569   -
570   - def lineno(self):
571   - """The current line number."""
572   - return self.current.lineno
573   - lineno = property(lineno, doc=lineno.__doc__)
574   -
575   - def __nonzero__(self):
576   - """Are we at the end of the tokenstream?"""
577   - return bool(self._pushed) or self.current.type != 'eof'
578   -
579   - eos = property(lambda x: not x.__nonzero__(), doc=__nonzero__.__doc__)
580   -
581   - def look(self):
582   - """See what's the next token."""
583   - if self._pushed:
584   - return self._pushed[-1]
585   - old_token = self.current
586   - self.next()
587   - new_token = self.current
588   - self.current = old_token
589   - self.push(new_token)
590   - return new_token
591   -
592   - def push(self, token):
593   - """Push a token back to the stream."""
594   - self._pushed.append(token)
595   -
596   - def skip(self, n):
597   - """Got n tokens ahead."""
598   - for x in xrange(n):
599   - self.next()
600   -
601   - def shift(self, token):
602   - """
603   - Push one token into the stream.
604   - """
605   - old_current = self.current
606   - self.next()
607   - self.push(self.current)
608   - self.push(old_current)
609   - self.push(token)
610   - self.next()
611   -
612   - def next(self):
613   - """Go one token ahead."""
614   - if self._pushed:
615   - self.current = self._pushed.pop()
616   - elif self.current.type != 'eof':
617   - try:
618   - self.current = self._next()
619   - except StopIteration:
620   - self.close()
621   -
622   - def read_whitespace(self):
623   - """Read all the whitespace, up to the next tag."""
624   - lineno = self.current.lineno
625   - buf = []
626   - while self.current.type == 'data' and not \
627   - self.current.value.strip():
628   - buf.append(self.current.value)
629   - self.next()
630   - if buf:
631   - return Token(lineno, 'data', u''.join(buf))
632   -
633   - def close(self):
634   - """Close the stream."""
635   - self.current = Token(self.current.lineno, 'eof', '')
636   - self._next = None
637   -
638   - def expect(self, token_type, token_value=_missing):
639   - """Expect a given token type and return it"""
640   - if self.current.type != token_type:
641   - raise TemplateSyntaxError("expected token %r, got %r" %
642   - (token_type, self.current.type),
643   - self.current.lineno,
644   - self.filename)
645   - elif token_value is not _missing and \
646   - self.current.value != token_value:
647   - raise TemplateSyntaxError("expected %r, got %r" %
648   - (token_value, self.current.value),
649   - self.current.lineno,
650   - self.filename)
651   - try:
652   - return self.current
653   - finally:
654   - self.next()
655   -
656   -
657   -class TemplateStream(object):
658   - """
659   - Wraps a genererator for outputing template streams.
660   - """
661   -
662   - def __init__(self, gen):
663   - self._gen = gen
664   - self._next = gen.next
665   - self.buffered = False
666   -
667   - def disable_buffering(self):
668   - """
669   - Disable the output buffering.
670   - """
671   - self._next = self._gen.next
672   - self.buffered = False
673   -
674   - def enable_buffering(self, size=5):
675   - """
676   - Enable buffering. Buffer `size` items before
677   - yielding them.
678   - """
679   - if size <= 1:
680   - raise ValueError('buffer size too small')
681   - self.buffered = True
682   -
683   - def buffering_next():
684   - buf = []
685   - c_size = 0
686   - push = buf.append
687   - next = self._gen.next
688   -
689   - try:
690   - while True:
691   - item = next()
692   - if item:
693   - push(item)
694   - c_size += 1
695   - if c_size >= size:
696   - raise StopIteration()
697   - except StopIteration:
698   - if not c_size:
699   - raise
700   - return u''.join(buf)
701   -
702   - self._next = buffering_next
703   -
704   - def __iter__(self):
705   - return self
706   -
707   - def next(self):
708   - return self._next()
213 jinja/debugger.py
... ... @@ -1,213 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -"""
3   - jinja.debugger
4   - ~~~~~~~~~~~~~~
5   -
6   - This module implements helper function Jinja uses to give the users a
7   - possibility to develop Jinja templates like they would debug python code.
8   - It seamlessly integreates into the python traceback system, in fact it
9   - just modifies the trackback stack so that the line numbers are correct
10   - and the frame information are bound to the context and not the frame of
11   - the template evaluation loop.
12   -
13   - To achive this it raises the exception it cought before in an isolated
14   - namespace at a given line. The locals namespace is set to the current
15   - template context.
16   -
17   - The traceback generated by raising that exception is then either returned
18   - or linked with the former traceback if the `jinja._debugger` module is
19   - available. Because it's not possible to modify traceback objects from the
20   - python space this module is needed for this process.
21   -
22   - If it's not available it just ignores the other frames. Because this can
23   - lead to actually harder to debug code there is a setting on the jinja
24   - environment to disable the debugging system.
25   -
26   - The isolated namespace which is used to raise the exception also contains
27   - a `__loader__` name that helds a reference to a PEP 302 compatible loader.
28   - Because there are currently some traceback systems (such as the paste
29   - evalexception debugger) that do not provide the frame globals when
30   - retrieving the source from the linecache module, Jinja injects the source
31   - to the linecache module itself and changes the filename to a URL style
32   - "virtual filename" so that Jinja doesn't acidentally override other files
33   - in the linecache.
34   -
35   - :copyright: 2007 by Armin Ronacher.
36   - :license: BSD, see LICENSE for more details.
37   -"""
38   -
39   -import sys
40   -from random import randrange
41   -
42   -# if we have extended debugger support we should really use it
43   -try:
44   - from jinja._debugger import *
45   - has_extended_debugger = True
46   -except ImportError:
47   - has_extended_debugger = False
48   -
49   -# we need the RUNTIME_EXCEPTION_OFFSET to skip the not used frames
50   -from jinja.utils import reversed, RUNTIME_EXCEPTION_OFFSET
51   -
52   -
53   -def fake_template_exception(exc_type, exc_value, tb, filename, lineno,
54   - source, context_or_env, tb_back=None):
55   - """
56   - Raise an exception "in a template". Return a traceback
57   - object. This is used for runtime debugging, not compile time.
58   - """
59   - # some traceback systems allow to skip frames
60   - __traceback_hide__ = True
61   -
62   - # create the namespace which will be the local namespace
63   - # of the new frame then. Some debuggers show local variables
64   - # so we better inject the context and not the evaluation loop context.
65   - from jinja.datastructure import Context
66   - if isinstance(context_or_env, Context):
67   - env = context_or_env.environment
68   - namespace = context_or_env.to_dict()
69   - else:
70   - env = context_or_env
71   - namespace = {}
72   -
73   - # no unicode for filenames
74   - if isinstance(filename, unicode):
75   - filename = filename.encode('utf-8')
76   -
77   - # generate an jinja unique filename used so that linecache
78   - # gets data that doesn't interfere with other modules
79   - if filename is None:
80   - vfilename = 'jinja://~%d' % randrange(0, 10000)
81   - filename = '<string>'
82   - else:
83   - vfilename = 'jinja://%s' % filename
84   -
85   - # now create the used loaded and update the linecache
86   - loader = TracebackLoader(env, source, filename)
87   - loader.update_linecache(vfilename)
88   - globals = {
89   - '__name__': vfilename,
90   - '__file__': vfilename,
91   - '__loader__': loader
92   - }
93   -
94   - # use the simple debugger to reraise the exception in the
95   - # line where the error originally occoured
96   - globals['__exception_to_raise__'] = (exc_type, exc_value)
97   - offset = '\n' * (lineno - 1)
98   - code = compile(offset + 'raise __exception_to_raise__[0], '
99   - '__exception_to_raise__[1]',
100   - vfilename or '<template>', 'exec')
101   - try:
102   - exec code in globals, namespace
103   - except:
104   - exc_info = sys.exc_info()
105   -
106   - # if we have an extended debugger we set the tb_next flag so that
107   - # we don't loose the higher stack items.
108   - if has_extended_debugger:
109   - if tb_back is not None:
110   - tb_set_next(tb_back, exc_info[2])
111   - if tb is not None:
112   - tb_set_next(exc_info[2].tb_next, tb.tb_next)
113   -
114   - # otherwise just return the exc_info from the simple debugger
115   - return exc_info
116   -
117   -
118   -def translate_exception(template, context, exc_type, exc_value, tb):
119   - """
120   - Translate an exception and return the new traceback.
121   - """
122   - # depending on the python version we have to skip some frames to
123   - # step to get the frame of the current template. The frames before
124   - # are the toolchain used to render that thing.
125   - for x in xrange(RUNTIME_EXCEPTION_OFFSET):
126   - tb = tb.tb_next
127   -
128   - result_tb = prev_tb = None
129   - initial_tb = tb
130   -
131   - # translate all the jinja frames in this traceback
132   - while tb is not None:
133   - if tb.tb_frame.f_globals.get('__jinja_template__'):
134   - debug_info = tb.tb_frame.f_globals['debug_info']
135   -
136   - # the next thing we do is matching the current error line against the
137   - # debugging table to get the correct source line. If we can't find the
138   - # filename and line number we return the traceback object unaltered.
139   - error_line = tb.tb_lineno
140   - for code_line, tmpl_filename, tmpl_line in reversed(debug_info):
141   - if code_line <= error_line:
142   - source = tb.tb_frame.f_globals['template_source']
143   - tb = fake_template_exception(exc_type, exc_value, tb,
144   - tmpl_filename, tmpl_line,
145   - source, context, prev_tb)[-1]
146   - break
147   - if result_tb is None:
148   - result_tb = tb
149   - prev_tb = tb
150   - tb = tb.tb_next
151   -
152   - # under some conditions we cannot translate any frame. in that
153   - # situation just return the original traceback.
154   - return (exc_type, exc_value, result_tb or intial_tb)
155   -
156   -
157   -def raise_syntax_error(exception, env, source=None):
158   - """
159   - This method raises an exception that includes more debugging
160   - informations so that debugging works better. Unlike
161   - `translate_exception` this method raises the exception with
162   - the traceback.
163   - """
164   - exc_info = fake_template_exception(exception, None, None,
165   - exception.filename,
166   - exception.lineno, source, env)
167   - raise exc_info[0], exc_info[1], exc_info[2]
168   -
169   -
170   -class TracebackLoader(object):
171   - """
172   - Fake importer that just returns the source of a template. It's just used
173   - by Jinja interally and you shouldn't use it on your own.
174   - """
175   -
176   - def __init__(self, environment, source, filename):
177   - self.loader = environment.loader
178   - self.source = source
179   - self.filename = filename
180   -
181   - def update_linecache(self, virtual_filename):
182   - """
183   - Hacky way to let traceback systems know about the
184   - Jinja template sourcecode. Very hackish indeed.
185   - """
186   - # check for linecache, not every implementation of python
187   - # might have such an module (this check is pretty senseless
188   - # because we depend on cpython anway)
189   - try:
190   - from linecache import cache
191   - except ImportError:
192   - return
193   - data = self.get_source(None)
194   - cache[virtual_filename] = (
195   - len(data),
196   - None,
197   - data.splitlines(True),
198   - virtual_filename
199   - )
200   -
201   - def get_source(self, impname):
202   - """Return the source as bytestring."""
203   - source = ''
204   - if self.source is not None:
205   - source = self.source
206   - elif self.loader is not None:
207   - try:
208   - source = self.loader.get_source(self.filename)
209   - except TemplateNotFound:
210   - pass
211   - if isinstance(source, unicode):
212   - source = source.encode('utf-8')
213   - return source
404 jinja/environment.py
... ... @@ -1,404 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -"""
3   - jinja.environment
4   - ~~~~~~~~~~~~~~~~~
5   -
6   - Provides a class that holds runtime and parsing time options.
7   -
8   - :copyright: 2007 by Armin Ronacher.
9   - :license: BSD, see LICENSE for more details.
10   -"""
11   -from jinja.lexer import Lexer
12   -from jinja.parser import Parser
13   -from jinja.loaders import LoaderWrapper
14   -from jinja.datastructure import SilentUndefined, Markup, Context, FakeTranslator
15   -from jinja.translators.python import PythonTranslator
16   -from jinja.utils import collect_translations, get_attribute
17   -from jinja.exceptions import FilterNotFound, TestNotFound, \
18   - SecurityException, TemplateSyntaxError
19   -from jinja.defaults import DEFAULT_FILTERS, DEFAULT_TESTS, DEFAULT_NAMESPACE
20   -
21   -
22   -__all__ = ['Environment']
23   -
24   -
25   -#: minor speedup
26   -_getattr = getattr
27   -
28   -
29   -class Environment(object):
30   - """
31   - The Jinja environment.
32   -
33   - The core component of Jinja is the `Environment`. It contains
34   - important shared variables like configuration, filters, tests,
35   - globals and others.
36   - """
37   -
38   - def __init__(self,
39   - block_start_string='{%',
40   - block_end_string='%}',
41   - variable_start_string='{{',
42   - variable_end_string='}}',
43   - comment_start_string='{#',
44   - comment_end_string='#}',
45   - trim_blocks=False,
46   - auto_escape=False,
47   - default_filters=None,
48   - template_charset='utf-8',
49   - charset='utf-8',
50   - namespace=None,
51   - loader=None,
52   - filters=None,
53   - tests=None,
54   - context_class=Context,
55   - undefined_singleton=SilentUndefined,
56   - disable_regexps=False,
57   - friendly_traceback=True,
58   - translator_factory=None,
59   - template_translator=PythonTranslator):
60   - """
61   - Here the possible initialization parameters:
62   -
63   - ========================= ============================================
64   - `block_start_string` * the string marking the begin of a block.
65   - this defaults to ``'{%'``.
66   - `block_end_string` * the string marking the end of a block.
67   - defaults to ``'%}'``.
68   - `variable_start_string` * the string marking the begin of a print
69   - statement. defaults to ``'{{'``.
70   - `comment_start_string` * the string marking the begin of a
71   - comment. defaults to ``'{#'``.
72   - `comment_end_string` * the string marking the end of a comment.
73   - defaults to ``'#}'``.
74   - `trim_blocks` * If this is set to ``True`` the first newline
75   - after a block is removed (block, not
76   - variable tag!). Defaults to ``False``.
77   - `auto_escape` If this is set to ``True`` Jinja will
78   - automatically escape all variables using xml
79   - escaping methods. If you don't want to
80   - escape a string you have to wrap it in a
81   - ``Markup`` object from the
82   - ``jinja.datastructure`` module. If
83   - `auto_escape` is ``True`` there will be also
84   - a ``Markup`` object in the template
85   - namespace to define partial html fragments.
86   - Note that we do not recommend this feature.
87   - `default_filters` list of tuples in the form (``filter_name``,
88   - ``arguments``) where ``filter_name`` is the
89   - name of a registered filter and
90   - ``arguments`` a tuple with the filter
91   - arguments. The filters specified here will
92   - always be applied when printing data to the
93   - template. *new in Jinja 1.1*
94   - `template_charset` The charset of the templates. Defaults
95   - to ``'utf-8'``.
96   - `charset` Charset of all string input data. Defaults
97   - to ``'utf-8'``.
98   - `namespace` Global namespace for all templates.
99   - `loader` Specify a template loader.
100   - `filters` dict of filters or the default filters if
101   - not defined.
102   - `tests` dict of tests of the default tests if not
103   - defined.
104   - `context_class` the context class this template should use.
105   - See the `Context` documentation for more
106   - details.
107   - `undefined_singleton` The singleton value that is used for missing
108   - variables. *new in Jinja 1.1*
109   - `disable_regexps` Disable support for regular expresssions.
110   - `friendly_traceback` Set this to `False` to disable the developer
111   - friendly traceback rewriting. Whenever an
112   - runtime or syntax error occours jinja will
113   - try to make a developer friendly traceback
114   - that shows the error in the template line.
115   - This however can be annoying when debugging
116   - broken functions that are called from the
117   - template. *new in Jinja 1.1*
118   - `translator_factory` A callback function that is called with
119   - the context as first argument to get the
120   - translator for the current instance.
121   - *new in Jinja 1.2*
122   - `template_translator` An class that defines a static method called
123   - process which can be used to process the
124   - template's AST into a compiled python module.
125   - *new in Jinja 1.2*
126   - ========================= ============================================
127   -
128   - All of these variables except those marked with a star (*) are
129   - modifiable after environment initialization.
130   - """
131   -
132   - # lexer / parser information
133   - self.block_start_string = block_start_string
134   - self.block_end_string = block_end_string
135   - self.variable_start_string = variable_start_string
136   - self.variable_end_string = variable_end_string
137   - self.comment_start_string = comment_start_string
138   - self.comment_end_string = comment_end_string
139   - self.trim_blocks = trim_blocks
140   -
141   - # other stuff
142   - self.template_charset = template_charset
143   - self.charset = charset
144   - self.loader = loader
145   - if filters is None:
146   - filters = DEFAULT_FILTERS.copy()
147   - self.filters = filters
148   - if tests is None:
149   - tests = DEFAULT_TESTS.copy()
150   - self.tests = tests
151   - self.default_filters = default_filters or []
152   - self.context_class = context_class
153   - self.undefined_singleton = undefined_singleton
154   - self.disable_regexps = disable_regexps
155   - self.friendly_traceback = friendly_traceback
156   -
157   - # global namespace
158   - if namespace is None:
159   - namespace = DEFAULT_NAMESPACE.copy()
160   - self.globals = namespace
161   -
162   - # jinja 1.0 compatibility
163   - if auto_escape:
164   - self.default_filters.append(('escape', (True,)))
165   - self.globals['Markup'] = Markup
166   -
167   - # and here the translator factory
168   - self.translator_factory = translator_factory
169   -
170   - # and here the AST translator
171   - self.template_translator = template_translator
172   -
173   - # create lexer
174   - self.lexer = Lexer(self)
175   -
176   - def loader(self, value):
177   - """
178   - Get or set the template loader.
179   - """
180   - self._loader = LoaderWrapper(self, value)
181   - loader = property(lambda s: s._loader, loader, doc=loader.__doc__)
182   -
183   - def parse(self, source, filename=None):
184   - """
185   - Parse the sourcecode and return the abstract syntax tree. This tree
186   - of nodes is used by the `translators`_ to convert the template into
187   - executable source- or bytecode.
188   -
189   - .. _translators: translators.txt
190   - """
191   - parser = Parser(self, source, filename)
192   - return parser.parse()
193   -
194   - def lex(self, source, filename=None):
195   - """
196   - Lex the given sourcecode and return a generator that yields tokens.
197   - The stream returned is not usable for Jinja but can be used if
198   - Jinja templates should be processed by other tools (for example
199   - syntax highlighting etc)
200   -
201   - The tuples are returned in the form ``(lineno, token, value)``.
202   - """
203   - return self.lexer.tokeniter(source, filename)
204   -
205   - def from_string(self, source):
206   - """
207   - Load and parse a template source and translate it into eval-able
208   - Python code. This code is wrapped within a `Template` class that
209   - allows you to render it.
210   - """
211   - from jinja.translators.python import PythonTranslator
212   - try:
213   - rv = PythonTranslator.process(self, Parser(self, source).parse(),
214   - source)
215   - except TemplateSyntaxError, e:
216   - # on syntax errors rewrite the traceback if wanted
217   - if not self.friendly_traceback:
218   - raise
219   - from jinja.debugger import raise_syntax_error
220   - if __debug__:
221   - __traceback_hide__ = True
222   - raise_syntax_error(e, self, source)
223   - else:
224   - return rv
225   -
226   - def get_template(self, filename):
227   - """
228   - Load a template from a loader. If the template does not exist, you
229   - will get a `TemplateNotFound` exception.
230   - """
231   - return self._loader.load(filename, translator=self.template_translator)
232   -
233   - def to_unicode(self, value):
234   - """
235   - Convert a value to unicode with the rules defined on the environment.
236   - """
237   - # undefined and None expand to ""
238   - if value in (None, self.undefined_singleton):
239   - return u''
240   - # things that are already unicode can pass. As long as nobody
241   - # does ugly things with the class it works for jinja too
242   - elif isinstance(value, unicode):
243   - return value
244   - # otherwise try to use __unicode__ or decode __str__
245   - try:
246   - return unicode(value)
247   - except UnicodeError:
248   - return str(value).decode(self.charset, 'ignore')
249   -
250   - def get_translator(self, context):
251   - """
252   - Return the translator for i18n.
253   -
254   - A translator is an object that provides the two functions
255   - ``gettext(string)`` and ``ngettext(singular, plural, n)``. Note
256   - that both of them have to return unicode!
257   - """
258   - if self.translator_factory is not None:
259   - return self.translator_factory(context)
260   - return FakeTranslator()
261   -
262   - def get_translations(self, name):
263   - """
264   - Load template `name` and return all translatable strings (note that
265   - that it really just returns the strings form this template, not from
266   - the parent or any included templates!)
267   - """
268   - return collect_translations(self.loader.parse(name))
269   -
270   - def get_translations_for_string(self, string):
271   - """
272   - Like `get_translations`, but the translations are loaded from a
273   - normal string that represents the template.
274   - """
275   - return collect_translations(self.parse(string))