NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

environment.py (21632B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\jinja2\environment.py
      2 import os
      3 import sys
      4 from jinja2 import nodes
      5 from jinja2.defaults import *
      6 from jinja2.lexer import get_lexer, TokenStream
      7 from jinja2.parser import Parser
      8 from jinja2.optimizer import optimize
      9 from jinja2.compiler import generate
     10 from jinja2.runtime import Undefined, new_context
     11 from jinja2.exceptions import TemplateSyntaxError, TemplateNotFound, TemplatesNotFound
     12 from jinja2.utils import import_string, LRUCache, Markup, missing, concat, consume, internalcode, _encode_filename
     13 _spontaneous_environments = LRUCache(10)
     14 _make_traceback = None
     15 
     16 def get_spontaneous_environment(*args):
     17     try:
     18         env = _spontaneous_environments.get(args)
     19     except TypeError:
     20         return Environment(*args)
     21 
     22     if env is not None:
     23         return env
     24     _spontaneous_environments[args] = env = Environment(*args)
     25     env.shared = True
     26     return env
     27 
     28 
     29 def create_cache(size):
     30     if size == 0:
     31         return None
     32     if size < 0:
     33         return {}
     34     return LRUCache(size)
     35 
     36 
     37 def copy_cache(cache):
     38     if cache is None:
     39         return
     40     if type(cache) is dict:
     41         return {}
     42     return LRUCache(cache.capacity)
     43 
     44 
     45 def load_extensions(environment, extensions):
     46     result = {}
     47     for extension in extensions:
     48         if isinstance(extension, basestring):
     49             extension = import_string(extension)
     50         result[extension.identifier] = extension(environment)
     51 
     52     return result
     53 
     54 
     55 def _environment_sanity_check(environment):
     56     return environment
     57 
     58 
     59 class Environment(object):
     60     sandboxed = False
     61     overlayed = False
     62     linked_to = None
     63     shared = False
     64     exception_handler = None
     65     exception_formatter = None
     66 
     67     def __init__(self, block_start_string = BLOCK_START_STRING, block_end_string = BLOCK_END_STRING, variable_start_string = VARIABLE_START_STRING, variable_end_string = VARIABLE_END_STRING, comment_start_string = COMMENT_START_STRING, comment_end_string = COMMENT_END_STRING, line_statement_prefix = LINE_STATEMENT_PREFIX, line_comment_prefix = LINE_COMMENT_PREFIX, trim_blocks = TRIM_BLOCKS, newline_sequence = NEWLINE_SEQUENCE, extensions = (), optimized = True, undefined = Undefined, finalize = None, autoescape = False, loader = None, cache_size = 50, auto_reload = True, bytecode_cache = None):
     68         self.block_start_string = block_start_string
     69         self.block_end_string = block_end_string
     70         self.variable_start_string = variable_start_string
     71         self.variable_end_string = variable_end_string
     72         self.comment_start_string = comment_start_string
     73         self.comment_end_string = comment_end_string
     74         self.line_statement_prefix = line_statement_prefix
     75         self.line_comment_prefix = line_comment_prefix
     76         self.trim_blocks = trim_blocks
     77         self.newline_sequence = newline_sequence
     78         self.undefined = undefined
     79         self.optimized = optimized
     80         self.finalize = finalize
     81         self.autoescape = autoescape
     82         self.filters = DEFAULT_FILTERS.copy()
     83         self.tests = DEFAULT_TESTS.copy()
     84         self.globals = DEFAULT_NAMESPACE.copy()
     85         self.loader = loader
     86         self.bytecode_cache = None
     87         self.cache = create_cache(cache_size)
     88         self.bytecode_cache = bytecode_cache
     89         self.auto_reload = auto_reload
     90         self.extensions = load_extensions(self, extensions)
     91         _environment_sanity_check(self)
     92 
     93     def add_extension(self, extension):
     94         self.extensions.update(load_extensions(self, [extension]))
     95 
     96     def extend(self, **attributes):
     97         for key, value in attributes.iteritems():
     98             if not hasattr(self, key):
     99                 setattr(self, key, value)
    100 
    101     def overlay(self, block_start_string = missing, block_end_string = missing, variable_start_string = missing, variable_end_string = missing, comment_start_string = missing, comment_end_string = missing, line_statement_prefix = missing, line_comment_prefix = missing, trim_blocks = missing, extensions = missing, optimized = missing, undefined = missing, finalize = missing, autoescape = missing, loader = missing, cache_size = missing, auto_reload = missing, bytecode_cache = missing):
    102         args = dict(locals())
    103         del args['self']
    104         del args['cache_size']
    105         del args['extensions']
    106         rv = object.__new__(self.__class__)
    107         rv.__dict__.update(self.__dict__)
    108         rv.overlayed = True
    109         rv.linked_to = self
    110         for key, value in args.iteritems():
    111             if value is not missing:
    112                 setattr(rv, key, value)
    113 
    114         if cache_size is not missing:
    115             rv.cache = create_cache(cache_size)
    116         else:
    117             rv.cache = copy_cache(self.cache)
    118         rv.extensions = {}
    119         for key, value in self.extensions.iteritems():
    120             rv.extensions[key] = value.bind(rv)
    121 
    122         if extensions is not missing:
    123             rv.extensions.update(load_extensions(rv, extensions))
    124         return _environment_sanity_check(rv)
    125 
    126     lexer = property(get_lexer, doc='The lexer for this environment.')
    127 
    128     def iter_extensions(self):
    129         return iter(sorted(self.extensions.values(), key=lambda x: x.priority))
    130 
    131     def getitem(self, obj, argument):
    132         try:
    133             return obj[argument]
    134         except (TypeError, LookupError):
    135             if isinstance(argument, basestring):
    136                 try:
    137                     attr = str(argument)
    138                 except Exception:
    139                     pass
    140                 else:
    141                     try:
    142                         return getattr(obj, attr)
    143                     except AttributeError:
    144                         pass
    145 
    146             return self.undefined(obj=obj, name=argument)
    147 
    148     def getattr(self, obj, attribute):
    149         try:
    150             return getattr(obj, attribute)
    151         except AttributeError:
    152             pass
    153 
    154         try:
    155             return obj[attribute]
    156         except (TypeError, LookupError, AttributeError):
    157             return self.undefined(obj=obj, name=attribute)
    158 
    159     @internalcode
    160     def parse(self, source, name = None, filename = None):
    161         try:
    162             return self._parse(source, name, filename)
    163         except TemplateSyntaxError:
    164             exc_info = sys.exc_info()
    165 
    166         self.handle_exception(exc_info, source_hint=source)
    167 
    168     def _parse(self, source, name, filename):
    169         return Parser(self, source, name, _encode_filename(filename)).parse()
    170 
    171     def lex(self, source, name = None, filename = None):
    172         source = unicode(source)
    173         try:
    174             return self.lexer.tokeniter(source, name, filename)
    175         except TemplateSyntaxError:
    176             exc_info = sys.exc_info()
    177 
    178         self.handle_exception(exc_info, source_hint=source)
    179 
    180     def preprocess(self, source, name = None, filename = None):
    181         return reduce(lambda s, e: e.preprocess(s, name, filename), self.iter_extensions(), unicode(source))
    182 
    183     def _tokenize(self, source, name, filename = None, state = None):
    184         source = self.preprocess(source, name, filename)
    185         stream = self.lexer.tokenize(source, name, filename, state)
    186         for ext in self.iter_extensions():
    187             stream = ext.filter_stream(stream)
    188             if not isinstance(stream, TokenStream):
    189                 stream = TokenStream(stream, name, filename)
    190 
    191         return stream
    192 
    193     def _generate(self, source, name, filename, defer_init = False):
    194         return generate(source, self, name, filename, defer_init=defer_init)
    195 
    196     def _compile(self, source, filename):
    197         return compile(source, filename, 'exec')
    198 
    199     @internalcode
    200     def compile(self, source, name = None, filename = None, raw = False, defer_init = False):
    201         source_hint = None
    202         try:
    203             if isinstance(source, basestring):
    204                 source_hint = source
    205                 source = self._parse(source, name, filename)
    206             if self.optimized:
    207                 source = optimize(source, self)
    208             source = self._generate(source, name, filename, defer_init=defer_init)
    209             if raw:
    210                 return source
    211             if filename is None:
    212                 filename = '<template>'
    213             else:
    214                 filename = _encode_filename(filename)
    215             return self._compile(source, filename)
    216         except TemplateSyntaxError:
    217             exc_info = sys.exc_info()
    218 
    219         self.handle_exception(exc_info, source_hint=source)
    220 
    221     def compile_expression(self, source, undefined_to_none = True):
    222         parser = Parser(self, source, state='variable')
    223         exc_info = None
    224         try:
    225             expr = parser.parse_expression()
    226             if not parser.stream.eos:
    227                 raise TemplateSyntaxError('chunk after expression', parser.stream.current.lineno, None, None)
    228             expr.set_environment(self)
    229         except TemplateSyntaxError:
    230             exc_info = sys.exc_info()
    231 
    232         if exc_info is not None:
    233             self.handle_exception(exc_info, source_hint=source)
    234         body = [nodes.Assign(nodes.Name('result', 'store'), expr, lineno=1)]
    235         template = self.from_string(nodes.Template(body, lineno=1))
    236         return TemplateExpression(template, undefined_to_none)
    237 
    238     def compile_templates(self, target, extensions = None, filter_func = None, zip = 'deflated', log_function = None, ignore_errors = True, py_compile = False):
    239         from jinja2.loaders import ModuleLoader
    240         if log_function is None:
    241             log_function = lambda x: None
    242         if py_compile:
    243             import imp, marshal
    244             py_header = imp.get_magic() + u'\xff\xff\xff\xff'.encode('iso-8859-15')
    245 
    246         def write_file(filename, data, mode):
    247             if zip:
    248                 info = ZipInfo(filename)
    249                 info.external_attr = 32309248L
    250                 zip_file.writestr(info, data)
    251             else:
    252                 f = open(os.path.join(target, filename), mode)
    253                 try:
    254                     f.write(data)
    255                 finally:
    256                     f.close()
    257 
    258         if zip is not None:
    259             from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED, ZIP_STORED
    260             zip_file = ZipFile(target, 'w', dict(deflated=ZIP_DEFLATED, stored=ZIP_STORED)[zip])
    261             log_function('Compiling into Zip archive "%s"' % target)
    262         else:
    263             if not os.path.isdir(target):
    264                 os.makedirs(target)
    265             log_function('Compiling into folder "%s"' % target)
    266         try:
    267             for name in self.list_templates(extensions, filter_func):
    268                 source, filename, _ = self.loader.get_source(self, name)
    269                 try:
    270                     code = self.compile(source, name, filename, True, True)
    271                 except TemplateSyntaxError as e:
    272                     if not ignore_errors:
    273                         raise
    274                     log_function('Could not compile "%s": %s' % (name, e))
    275                     continue
    276 
    277                 filename = ModuleLoader.get_module_filename(name)
    278                 if py_compile:
    279                     c = self._compile(code, _encode_filename(filename))
    280                     write_file(filename + 'c', py_header + marshal.dumps(c), 'wb')
    281                     log_function('Byte-compiled "%s" as %s' % (name, filename + 'c'))
    282                 else:
    283                     write_file(filename, code, 'w')
    284                     log_function('Compiled "%s" as %s' % (name, filename))
    285 
    286         finally:
    287             if zip:
    288                 zip_file.close()
    289 
    290         log_function('Finished compiling templates')
    291 
    292     def list_templates(self, extensions = None, filter_func = None):
    293         x = self.loader.list_templates()
    294         if extensions is not None:
    295             if filter_func is not None:
    296                 raise TypeError('either extensions or filter_func can be passed, but not both')
    297             filter_func = lambda x: '.' in x and x.rsplit('.', 1)[1] in extensions
    298         if filter_func is not None:
    299             x = filter(filter_func, x)
    300         return x
    301 
    302     def handle_exception(self, exc_info = None, rendered = False, source_hint = None):
    303         global _make_traceback
    304         if exc_info is None:
    305             exc_info = sys.exc_info()
    306         if _make_traceback is None:
    307             from jinja2.debug import make_traceback as _make_traceback
    308         traceback = _make_traceback(exc_info, source_hint)
    309         if rendered and self.exception_formatter is not None:
    310             return self.exception_formatter(traceback)
    311         if self.exception_handler is not None:
    312             self.exception_handler(traceback)
    313         exc_type, exc_value, tb = traceback.standard_exc_info
    314         raise exc_type, exc_value, tb
    315 
    316     def join_path(self, template, parent):
    317         return template
    318 
    319     @internalcode
    320     def _load_template(self, name, globals):
    321         if self.loader is None:
    322             raise TypeError('no loader for this environment specified')
    323         if self.cache is not None:
    324             template = self.cache.get(name)
    325             if template is not None and (not self.auto_reload or template.is_up_to_date):
    326                 return template
    327         template = self.loader.load(self, name, globals)
    328         if self.cache is not None:
    329             self.cache[name] = template
    330         return template
    331 
    332     @internalcode
    333     def get_template(self, name, parent = None, globals = None):
    334         if isinstance(name, Template):
    335             return name
    336         if parent is not None:
    337             name = self.join_path(name, parent)
    338         return self._load_template(name, self.make_globals(globals))
    339 
    340     @internalcode
    341     def select_template(self, names, parent = None, globals = None):
    342         if not names:
    343             raise TemplatesNotFound(message=u'Tried to select from an empty list of templates.')
    344         globals = self.make_globals(globals)
    345         for name in names:
    346             if isinstance(name, Template):
    347                 return name
    348             if parent is not None:
    349                 name = self.join_path(name, parent)
    350             try:
    351                 return self._load_template(name, globals)
    352             except TemplateNotFound:
    353                 pass
    354 
    355         raise TemplatesNotFound(names)
    356 
    357     @internalcode
    358     def get_or_select_template(self, template_name_or_list, parent = None, globals = None):
    359         if isinstance(template_name_or_list, basestring):
    360             return self.get_template(template_name_or_list, parent, globals)
    361         if isinstance(template_name_or_list, Template):
    362             return template_name_or_list
    363         return self.select_template(template_name_or_list, parent, globals)
    364 
    365     def from_string(self, source, globals = None, template_class = None):
    366         globals = self.make_globals(globals)
    367         cls = template_class or self.template_class
    368         return cls.from_code(self, self.compile(source), globals, None)
    369 
    370     def make_globals(self, d):
    371         if not d:
    372             return self.globals
    373         return dict(self.globals, **d)
    374 
    375 
    376 class Template(object):
    377 
    378     def __new__(cls, source, block_start_string = BLOCK_START_STRING, block_end_string = BLOCK_END_STRING, variable_start_string = VARIABLE_START_STRING, variable_end_string = VARIABLE_END_STRING, comment_start_string = COMMENT_START_STRING, comment_end_string = COMMENT_END_STRING, line_statement_prefix = LINE_STATEMENT_PREFIX, line_comment_prefix = LINE_COMMENT_PREFIX, trim_blocks = TRIM_BLOCKS, newline_sequence = NEWLINE_SEQUENCE, extensions = (), optimized = True, undefined = Undefined, finalize = None, autoescape = False):
    379         env = get_spontaneous_environment(block_start_string, block_end_string, variable_start_string, variable_end_string, comment_start_string, comment_end_string, line_statement_prefix, line_comment_prefix, trim_blocks, newline_sequence, frozenset(extensions), optimized, undefined, finalize, autoescape, None, 0, False, None)
    380         return env.from_string(source, template_class=cls)
    381 
    382     @classmethod
    383     def from_code(cls, environment, code, globals, uptodate = None):
    384         namespace = {'environment': environment,
    385          '__file__': code.co_filename}
    386         exec code in namespace
    387         rv = cls._from_namespace(environment, namespace, globals)
    388         rv._uptodate = uptodate
    389         return rv
    390 
    391     @classmethod
    392     def from_module_dict(cls, environment, module_dict, globals):
    393         return cls._from_namespace(environment, module_dict, globals)
    394 
    395     @classmethod
    396     def _from_namespace(cls, environment, namespace, globals):
    397         t = object.__new__(cls)
    398         t.environment = environment
    399         t.globals = globals
    400         t.name = namespace['name']
    401         t.filename = namespace['__file__']
    402         t.blocks = namespace['blocks']
    403         t.root_render_func = namespace['root']
    404         t._module = None
    405         t._debug_info = namespace['debug_info']
    406         t._uptodate = None
    407         namespace['environment'] = environment
    408         namespace['__jinja_template__'] = t
    409         return t
    410 
    411     def render(self, *args, **kwargs):
    412         vars = dict(*args, **kwargs)
    413         try:
    414             return concat(self.root_render_func(self.new_context(vars)))
    415         except Exception:
    416             exc_info = sys.exc_info()
    417 
    418         return self.environment.handle_exception(exc_info, True)
    419 
    420     def stream(self, *args, **kwargs):
    421         return TemplateStream(self.generate(*args, **kwargs))
    422 
    423     def generate(self, *args, **kwargs):
    424         vars = dict(*args, **kwargs)
    425         try:
    426             for event in self.root_render_func(self.new_context(vars)):
    427                 yield event
    428 
    429         except Exception:
    430             exc_info = sys.exc_info()
    431         else:
    432             return
    433 
    434         yield self.environment.handle_exception(exc_info, True)
    435 
    436     def new_context(self, vars = None, shared = False, locals = None):
    437         return new_context(self.environment, self.name, self.blocks, vars, shared, self.globals, locals)
    438 
    439     def make_module(self, vars = None, shared = False, locals = None):
    440         return TemplateModule(self, self.new_context(vars, shared, locals))
    441 
    442     @property
    443     def module(self):
    444         if self._module is not None:
    445             return self._module
    446         self._module = rv = self.make_module()
    447         return rv
    448 
    449     def get_corresponding_lineno(self, lineno):
    450         for template_line, code_line in reversed(self.debug_info):
    451             if code_line <= lineno:
    452                 return template_line
    453 
    454         return 1
    455 
    456     @property
    457     def is_up_to_date(self):
    458         if self._uptodate is None:
    459             return True
    460         return self._uptodate()
    461 
    462     @property
    463     def debug_info(self):
    464         return [ tuple(map(int, x.split('='))) for x in self._debug_info.split('&') ]
    465 
    466     def __repr__(self):
    467         if self.name is None:
    468             name = 'memory:%x' % id(self)
    469         else:
    470             name = repr(self.name)
    471         return '<%s %s>' % (self.__class__.__name__, name)
    472 
    473 
    474 class TemplateModule(object):
    475 
    476     def __init__(self, template, context):
    477         self._body_stream = list(template.root_render_func(context))
    478         self.__dict__.update(context.get_exported())
    479         self.__name__ = template.name
    480 
    481     def __html__(self):
    482         return Markup(concat(self._body_stream))
    483 
    484     def __str__(self):
    485         return unicode(self).encode('utf-8')
    486 
    487     def __unicode__(self):
    488         return concat(self._body_stream)
    489 
    490     def __repr__(self):
    491         if self.__name__ is None:
    492             name = 'memory:%x' % id(self)
    493         else:
    494             name = repr(self.__name__)
    495         return '<%s %s>' % (self.__class__.__name__, name)
    496 
    497 
    498 class TemplateExpression(object):
    499 
    500     def __init__(self, template, undefined_to_none):
    501         self._template = template
    502         self._undefined_to_none = undefined_to_none
    503 
    504     def __call__(self, *args, **kwargs):
    505         context = self._template.new_context(dict(*args, **kwargs))
    506         consume(self._template.root_render_func(context))
    507         rv = context.vars['result']
    508         if self._undefined_to_none and isinstance(rv, Undefined):
    509             rv = None
    510         return rv
    511 
    512 
    513 class TemplateStream(object):
    514 
    515     def __init__(self, gen):
    516         self._gen = gen
    517         self.disable_buffering()
    518 
    519     def dump(self, fp, encoding = None, errors = 'strict'):
    520         close = False
    521         if isinstance(fp, basestring):
    522             fp = file(fp, 'w')
    523             close = True
    524         try:
    525             if encoding is not None:
    526                 iterable = (x.encode(encoding, errors) for x in self)
    527             else:
    528                 iterable = self
    529             if hasattr(fp, 'writelines'):
    530                 fp.writelines(iterable)
    531             else:
    532                 for item in iterable:
    533                     fp.write(item)
    534 
    535         finally:
    536             if close:
    537                 fp.close()
    538 
    539     def disable_buffering(self):
    540         self._next = self._gen.next
    541         self.buffered = False
    542 
    543     def enable_buffering(self, size = 5):
    544         if size <= 1:
    545             raise ValueError('buffer size too small')
    546 
    547         def generator(next):
    548             buf = []
    549             c_size = 0
    550             push = buf.append
    551             while 1:
    552                 try:
    553                     while c_size < size:
    554                         c = next()
    555                         push(c)
    556                         if c:
    557                             c_size += 1
    558 
    559                 except StopIteration:
    560                     if not c_size:
    561                         return
    562 
    563                 yield concat(buf)
    564                 del buf[:]
    565                 c_size = 0
    566 
    567         self.buffered = True
    568         self._next = generator(self._gen.next).next
    569 
    570     def __iter__(self):
    571         return self
    572 
    573     def next(self):
    574         return self._next()
    575 
    576 
    577 Environment.template_class = Template